Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

jni: add a quick readme

  • Loading branch information...
commit 8a614eb5361a7b792e46aa3f2cb72408fd7bf8d3 1 parent 63c6f37
Cory Fields authored
Showing with 150 additions and 0 deletions.
  1. +150 −0 xbmc/android/jni/README
View
150 xbmc/android/jni/README
@@ -0,0 +1,150 @@
+(soon-to-be) libjni-android
+
+Quick and dirty readme.
+
+1. What is this?
+
+It is a native wrapper for JNI specifically designed to provide easy access
+to the Android API. The goal is to create a 1:1 mapping of java functionality
+to native apps.
+
+2. Is that possible?
+
+No. But we can try :)
+Java and c++ have some fundamental differences that make an exact mapping
+impossible. But we can come close.
+
+3. How does it work?
+
+The native classes use JNI to call into java while hiding the gory details from
+the user. Under the hood it's quite un-elegant. Typical JNI objects created and
+passed around using a thin wrapper. This wrapper is a heavily modified version
+of one found in libcrystax. Thanks crystax!
+
+4. What does it look like?
+
+ Here's a quick example:
+
+ void MyFunction()
+ {
+ // Find the launch intent for a package and start its activity
+ CJNIPackageManager manager = getPackageManager();
+ CJNIIntent intent = manager.getLaunchIntentForPackage("org.xbmc.xbmc");
+ startActivity(sendIntent);
+ }
+
+This tiny bit of functionality would require dozens of lines if using JNI
+directly, but here it looks just like java code.
+
+5. How do I use it in my app?
+It is assumed that you are using a NativeActivity. Apps should create a main
+class that inherits from CJNIContext, and passes android_app->state->clazz to
+the constructor. This class now acts like a standard NativeActivity which
+inherits from Context. This class can now call the same functions that a Java
+activity can. Additionally, a virtual OnReceive function will catch broadcast
+events.
+
+TODO: Rename and make the distinction between NativeActivity and Context
+classes.
+
+6. How do I interact with the classes?
+
+Just as you would with java. There is no documentation for usage, because the
+Android API documentation should be sufficient.
+
+7. What are the caveats?
+
+With any luck, very few. This library is still very new and has not been
+exposed to many use-cases yet. Here are a few:
+
+a. Java can return NULL objects (not null-pointers).
+workaround: objects can be tested as a bool.
+
+Here's an example of a function that would crash:
+
+ void MyFunction()
+ {
+ std::string externalDir = getExternalFilesDir("foo").getAbsolutePath();
+ return externalDir;
+ }
+
+The Android API specifies that getExternalFilesDir("") can return NULL if the
+path is not found. Thus getAbsolutePath() has no instance and would crash when
+called.
+
+The fix:
+
+ std::string MyFunction()
+ {
+ std::string externalDir;
+ CJNIFile myFile = getExternalFilesDir("foo");
+ if (myFile)
+ externalDir myFile.getAbsolutePath();
+ retrun externalDir;
+ }
+
+b. Probably lots more.
+
+8. Is the entire API implemented?
+Not even close! Classes and individual functions have been added as-needed.
+
+9. OK, how do I add xyz class?
+Each (non-static) class inherits from CJNIBase. This class stores an object
+for the subclass, handles copying, etc. The class is expected to provide
+functions and members of the same name as the Android api. Helper functions
+are used to make JNI usage less painful.
+
+Simplified Example:
+
+ #include "JNIBase.h"
+ class CJNISomeClass : public CJNIBase
+ {
+ public:
+ CJNISomeClass();
+ CJNISomeClass(const jni::jhobject &object) : CJNIBase(object){};
+ std::string getSomeString();
+ };
+
+ CJNISomeClass::CJNISomeClass() : CJNIBase("android/some/ClassName")
+ {
+ m_object = new_object(GetClassName());
+ }
+
+ std::string CJNISomeClass::getSomeString()
+ {
+ return jcast<std::string>(call_method<jhstring>(m_object, "getSomeString", "()Ljava/lang/String;"));
+ }
+
+When a CJNISomeClass is created, it will use the hard-coded classname to
+construct a new instance (<init> is called on the class).
+If a CJNISomeClass is created from another CJNISomeClass, its underlying object
+will be used to create a new copy.
+
+Note that jhobjects can be cast to and from their parent classes. This is to
+facilitate easy chaining of functions.
+
+new_object and call_method are helper functions that do auto-lookups and
+casting of params and the result. See jutils/jutils-details.hpp for more
+helpers.
+
+10. What is the lifetime of the created objects?
+All native objects are returned as Global refs. This is overkill, but it was
+done in order to reduce complexity. All refs are automatically destroyed when
+objects go out of scope. Because of this, all objects should be passed as
+const ref whenever possible to avoid unnecessary reference creation.
+
+CJNISomeClass objects should almost never be long-lived, as some environments
+may have hard-limits for the amount that can be allocated.
+
+11. Why bother? Aren't there programs to generate these wrappers automatically?
+Sure, but none of them seemed to do it in a way that reduced complexity to a
+nominal level.
+
+12. Is it stable?
+It works as-tested, but hasn't seen much real-world exposure. Time will tell.
+Don't use it in production.
+
+13. What's with the CJNI naming?
+This library was created for XBMC and classes were created using XBMC
+naming conventions. If it is adopted elsewhere, the names should be changed to
+something more standard.
Please sign in to comment.
Something went wrong with that request. Please try again.