Skip to content

Instantly share code, notes, and snippets.

@Noitidart
Last active November 19, 2020 13:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Noitidart/400261f83b1be721a93a to your computer and use it in GitHub Desktop.
Save Noitidart/400261f83b1be721a93a to your computer and use it in GitHub Desktop.
_ff-addon-tutorial-jniAndroidToast - Using js-ctypes to use JNI to call functions from the Android API, this specific example does the same as the NativeWindow component, it creates a toast message as seen here: https://developer.mozilla.org/en-US/Add-ons/Firefox_for_Android/API/NativeWindow/toast
var my_jenv = null;
try {
my_jenv = JNI.GetForThread();
// We declare the classes, methods, etc we will be using: this part is not seen in the native example
var SIG = {
CharSequence: 'Ljava/lang/CharSequence;',
Context: 'Landroid/content/Context;',
GeckoAppShell: 'Lorg.mozilla.gecko.GeckoAppShell;',
Toast: 'Landroid/widget/Toast;', // can use .'s or /'s so `android.widget.Toast` and `android/widget/Toast` both work // from docs page header http://developer.android.com/reference/android/widget/Toast.html#makeText%28android.content.Context,%20int,%20int%29
int: 'I', // from https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp9502
void: 'V' // from http://www.rgagnon.com/javadetails/java-0286.html
};
var Toast = JNI.LoadClass(my_jenv, SIG.Toast.substr(1, SIG.Toast.length - 2), {
static_fields: [
{ name: 'LENGTH_SHORT', sig: SIG.int }],
static_methods: [
{ name: 'makeText', sig: '(' + SIG.Context + SIG.CharSequence + SIG.int + ')' + SIG.Toast } // http://developer.android.com/reference/android/widget/Toast.html#makeText%28android.content.Context,%20int,%20int%29
],
methods: [
{ name: 'show', sig: '()' + SIG.void } // http://developer.android.com/reference/android/widget/Toast.html#show%28%29
]
});
var geckoAppShell = JNI.LoadClass(my_jenv, SIG.GeckoAppShell.substr(1, SIG.GeckoAppShell.length - 2), {
static_methods: [
{ name: 'getContext', sig: '()' + SIG.Context }
]
});
// ok this ends the JNI specific stuff, now below you will see native-by-jni side-by-side
// Context context = getApplicationContext();
var context = geckoAppShell.getContext();
// CharSequence text = 'Hello toast!';
var text = 'Hello toast!';
// int duration = Toast.LENGTH_SHORT;
var duration = Toast.LENGTH_SHORT;
// Toast toast = Toast.makeText(context, text, duration);
var toast = Toast.makeText(context, text, duration);
toast.show();
} finally {
if (my_jenv) {
JNI.UnloadClasses(my_jenv);
}
}
@Noitidart
Copy link
Author

README

Screencast to go along with this Gist showing you how to execute this code from WebIDE on your desktop to your mobile device: Youtube Screencast :: FxAndroid - JNI js-ctypes Toast

Rev1 - Rev8

  • Based on the original native code from the android docs page:

    Context context = getApplicationContext();
    CharSequence text = "Hello toast!";
    int duration = Toast.LENGTH_SHORT;
    
    Toast toast = Toast.makeText(context, text, duration);
    toast.show();
    
  • Revisions from the start of the conversion to the end of it, Rev8 works can copy-paste-run via webide it from scratchpad or drop it into your firefox for android addon, and then Rev9 is cleaned up version of it in preparation for upload to MDN

Rev9

  • Cleaned up and in working order (can copy-paste-run form scrachpad of webide attached to firefox on android device or emulator) here is a list of the resources used to get here
    • http://developer.android.com/guide/topics/ui/notifiers/toasts.html

    • http://developer.android.com/reference/android/widget/Toast.html#show%28%29

    • http://www.rgagnon.com/javadetails/java-0286.html

    • https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp9502

    • http://mxr.mozilla.org/mozilla-central/source/mobile/android/modules/JNI.jsm#884 (its weird we thought this was evidence that if we pass to LoadClass with L and ; around it, the JNI.jsm would remove it, but it's not, possible bug? So I had to do the .substr above)

    • I switched to using my_jenv in place of jenv because the global window object has a jenv variable

    • https://gist.github.com/Noitidart/a67e7556027889070bb6#file-gistfile1-txt-L6-L10

    • These resources were used as reference and understanding of JNI.jsm was used but not needed for this specific example (but I did lift the geckoShell thing from here for the Context) :

    • Not possible without the chat from @capella, @wesj, and @rnewman:

      04:23:50: <noida> Any JNI experienced users here? I was trying to learn but need help, i wanted to request some snippets of the side-by-side jni-by-native so i can learn and teach others via mdn. would anyone be available?
      04:28:14: <mfinkle> st3fan: we didn't send anything to macminicolo
      04:56:33: <rnewman> st3fan: where did you get that message?
      04:57:31: <rnewman> noida that's a pretty big undertaking, and the people who know it best are overcommitted or on vacation.
      04:58:34: <noida> thanks much for that msg
      04:58:41: <noida> im trying to learn so i can take a screenshot on android
      04:58:55: <rnewman> from an add-on?
      04:58:58: <noida> yep
      04:59:08: <noida> natively though i got it done for windows, gtk, and osx, just need ot add android
      04:59:09: <rnewman> of the whole UI?
      04:59:13: <noida> https://github.com/Noitidart/NativeShot
      04:59:31: <noida> well either right away
      04:59:37: <noida> or if two finger touch then delayed shot
      04:59:40: <rnewman> do you know what js-ctypes is?
      04:59:47: <noida> i wrote the docs baby
      04:59:55: <rnewman> perfect
      05:00:09: <noida> the jni is also done via ctypes
      05:00:13: <noida> so i wanted to teach othrs
      05:00:14: <rnewman> then give me ten minutes to get home and I'll look for an example to work with
      05:00:26: <noida> no way
      05:00:29: <noida> thank you so much!
      05:00:35: <noida> lots of people will use what you teach me right away
      05:00:45: <noida> a user on stackoverflow also asked how to take native screenshot on android
      05:00:53: <noida> ive been searching for someone for a week i super duper appreciate it!
      05:01:05: <noida> https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Standard_OS_Libraries
      05:01:11: <noida> thats example of one of my writings
      05:01:15: <noida> arai and i tag teamed it
      05:01:29: <noida> i also wrote how to use COM from jsctypes https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Examples/Using_COM_from_js-ctypes
      05:01:47: <noida> im not a C or C++ guy i learned stuff in reverse haha
      05:02:02: <noida> so arai helped me write the c++ and C working examples
      05:02:22: <noida> objc im pretty darn good at now the osx screenshot wwas a mix of corefoundation and objc
      05:02:48: <noida> but arai wrote the objc equivalent of the COM tutorial (for text to voice) https://developer.mozilla.org/en-US/docs/Mozilla/js-ctypes/Examples/Using_Objective-C_from_js-ctypes
      05:03:02: <noida> so soon you'll see a JNI page and sections too :)
      05:03:26: <noida> once i learn just need those darn side by side examples :( haha
      05:04:15: <noida> i also reached out to the auhtor of the jni module requesting a jni version of the simple toast native code i posted: https://github.com/cscott/intent-addon/issues/2#issuecomment-120650354
      05:05:14: <noida> that will then help figure out the screenshot hting and help here https://github.com/cscott/intent-addon/issues/1 and here http://stackoverflow.com/questions/30721525/is-it-possible-to-take-screenshots-from-firefox-for-android-extension
      05:06:19: <noida> haha sorry i got excited :P
      05:06:48: <Capella> noida: getting seriously dangerous :)
      05:06:56: <noida> dood i found my guy! :D
      05:07:14: <noida> and i was about to go to sleep thank god i didnt :D
      05:07:31: <Capella> oh yah, rnewman is up there when he's got time from like 1,000 other things ;)
      05:07:44: <rnewman> noida: http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js
      05:08:17: <Capella> "sleep", yah, I noticed you're not doing a lot of the lately :p
      05:08:17: <noida> thx! reading
      05:08:25: <noida> hahahaha ya man shoot
      05:08:29: <noida> im on a roll with nativeshot man
      05:08:45: <Capella> new projects are the best
      05:09:06: <rnewman> noida: next step is to figure out how to get a screenshot on Android
      05:09:46: <noida> thanks so much that would be awesome spoon feeding for my addon but ideally i was hoping to learn how to read the docs and then write my own jni
      05:09:50: <rnewman> to get the app itself is fairly easy: get the root view (from the activity, from the context)
      05:10:03: <rnewman> then http://stackoverflow.com/a/16109978/22003
      05:10:17: <rnewman> and you should be able to do all that via JNI.jsm
      05:10:20: <noida> like the docs have lots of native examples. like with objc arai taught me that you have to objc_msgsend stuff and some other stuff he taught me like variadic and jsctypes needs it typed then i ran from there
      05:10:42: <noida> oh fantastic small example
      05:10:46: <rnewman> if you want to reimplement JNI.jsm… well, you could do that, or you could improve it
      05:11:02: <noida> can we plz go with straight writing it. the one for one really helps me learn
      05:11:13: <noida> then learning about the ins and outs to improve it is where my learning really cements
      05:11:14: <rnewman> it's not super complicated, at least
      05:11:33: <noida> btw thx soooo much for this ive been dying for this!
      05:11:40: <noida> im starting up my tablet and hooking up webide :D
      05:11:57: <rnewman> :)
      05:13:03: <noida> ok all set up im going to run that testJNI stuff through
      05:13:17: <noida> on my own i learned this much
      05:13:19: <noida> jenv = JNI.GetForThread(); must be done :P
      05:13:20: <noida> hahaha
      05:13:30: <noida> and if i went into worker i have to do that in there firs thing
      05:18:54: <noida> so i also figured out i have to get the app context
      05:18:58: <noida> which is done with the loadclass org.mozilla.gecko.GeckoAppShell
      05:19:06: <noida> so those two things i will do in every jni script
      05:19:30: <noida> but i is LoadClass like objc_sel where it gets functions?
      05:19:57: <noida> as i dont see us doing any ctypes.declare which is obvious as the ctypes got us the JNI framework and now we should use the JNI equivalent of ctypes.declare
      05:20:03: <noida> so would that be LoadClass?
      05:20:18: <noida> so like org/mozilla/gecko/GeckoNetworkManager would be the lib name?
      05:20:32: <noida> and then getMNC and getMCC would be functions from that lib?
      05:21:12: <noida> and sig is the arguments that function receives?
      05:22:06: <noida> so thats what i was thinking. but hten i got super confused when i saw LoadClass with no storage into a var
      05:22:14: <noida> so now why do that when no plans to use that function?
      05:24:39: <rnewman> noida: sorry, I was reviewing some stuff
      05:24:45: <noida> np thx "D
      05:24:48: <noida> :D
      05:25:27: <rnewman> LoadClass is where you get a reference to the class itself; a la https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/jniTOC.html
      05:25:45: <rnewman> GeckoNetworkManager is a class; getMNC are static methods on that class
      05:26:17: <noida> the GeckoNetworkManager is not in android docs though
      05:26:17: <rnewman> so http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js#29
      05:26:46: <noida> no surprise, but im trying to approach this from a total noob standpoint, which i am really i dont know any java
      05:26:49: <rnewman> no, it's here: http://mxr.mozilla.org/mozilla-central/source/mobile/android/base/GeckoNetworkManager.java
      05:27:16: <noida> o super! so we are basically doing https://dutherenverseauborddelatable.wordpress.com/?s=libxul
      05:27:25: <noida> but rather then moz c internals. this is moz java internals
      05:27:26: <rnewman> so there are basically four things in Java: primitives (int), interfaces (Iterable), classes (String), and methods (getLength)
      05:27:40: <rnewman> there are two kinds of methods: static and instance
      05:28:03: <rnewman> GeckoNetworkManager.getMNC() is a static method call
      05:28:12: <noida> thanks this explanation is so prefect for me and docs!
      05:28:31: <rnewman> new String("foo").substring(1,2) is an instance method call
      05:28:58: <rnewman> (and a constructor call, which is a special kind of class method that returns an instance)
      05:29:22: <rnewman> JNI.jsm lets you get JavaScript objects that represent each of these things
      05:29:38: <rnewman> JNI.LoadClass gives you a class, for example
      05:29:59: <rnewman> the {static_methods: ...} bit lets you tell JNI.jsm which static methods to define for you
      05:30:15: <rnewman> those will be defined as JS methods on the object that LoadClass gives you
      05:30:38: <rnewman> makes sense?
      05:30:53: <noida> i think so :)
      05:31:11: <noida> and methods are what we use to do stuff like screenshot right?
      05:31:21: <noida> or make a toast?
      05:31:27: <noida> and show a toast?
      05:32:57: <noida> or if we follow along here: http://developer.android.com/guide/topics/ui/notifiers/toasts.html
      05:32:58: <rnewman> methods are functions that are tied to an object
      05:33:01: <noida> setGravity is a method?
      05:33:11: <rnewman> within a method, there's always an implicit variable 'this' that refers to the object
      05:33:18: <noida> ah
      05:33:30: <rnewman> so `setGravity` is an instance method of `Toast`
      05:33:38: <noida> oooo
      05:34:09: <rnewman> `makeText` is a class method of Toast
      05:34:26: <noida> o real interesting!
      05:34:29: <rnewman> so you could do `Toast.makeText(context, "foo", 5).setGravity(…)`
      05:34:33: <rnewman> see the difference?
      05:34:38: <noida> ya totally!!
      05:34:41: <noida> thx!
      05:37:47: <noida> im trying to use what you showed me to translate the examples in this dos page to jni
      05:38:32: <noida> ill have some q's in a sec plz. like ctypes.char.array()('asdf') is null terminated string, but here its diff. and numbers etc. and i dont know where they look up and get these ()I L() things
      05:41:38: <rnewman> https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/design.html#wp615
      05:41:43: <rnewman> JNI is pretty complicated
      05:41:58: <rnewman> it's a representation of the Java class/method resolution system and type system
      05:42:37: <rnewman> see Type Signatures here: https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp9502
      05:42:54: <noida> ah th
      05:42:55: <noida> thx
      05:42:58: <rnewman> so L means class, I means int
      05:42:59: <rnewman> etc. etc.
      05:43:13: <noida> ah this types page is exactly what i needed to understand that
      05:43:18: <noida> so right now im trying to create string
      05:43:23: <noida> so i saw this:
      05:43:36: <noida> CharSequence text = "Hello toast!";
      05:43:39: <noida> on docs page
      05:43:46: <noida> then i searched for CharSequence on doc
      05:43:53: <noida> then found this:
      05:44:10: <noida> https://github.com/cscott/intent-addon/blob/master/lib/main.js#L111
      05:44:36: <noida> so im trying to pull off Ljava/lang/String;Ljava/lang/CharSequence;
      05:45:50: <rnewman> so Java strings *are* charsequences
      05:46:02: <rnewman> and JNI.jsm should automatically bridge JS strings
      05:46:06: <rnewman> so just use "Hello"
      05:47:10: <noida> i just copied pasted but trying to defined i right now
      05:47:10: <noida> https://gist.github.com/Noitidart/400261f83b1be721a93a
      05:47:51: <noida> so line 14 and 15 are wrong easily. just comitted to show u my work so far :P
      05:49:19: <noida> plz dont give up on me thinking jni is too complicated for me i do com/vtable stuff from jsctypes i can pull this off i promise!
      05:49:20: <rnewman> yeah, you'd need to LoadClass Uri and Intent
      05:49:35: <rnewman> it's a good start!
      05:49:45: <noida> thx :D
      05:50:03: <noida> but because im doing toast i should load uri and intent i should load Toast right?
      05:50:14: <rnewman> you need to LoadClass every class you use
      05:50:15: <noida> docs say Toast is a class: http://developer.android.com/reference/android/widget/Toast.html
      05:55:43: <noida> so in the sig of a method
      05:55:49: <noida> args are seperated by ; ?
      05:55:50: <noida> sig: "(Ljava/lang/String;Ljava/lang/CharSequence;)"+Intent },
      05:55:58: <noida> so for makeText im thinking:
      05:55:58: <Capella> robocop still doesn't get gecko content for it's screenshots iirc (for whatever reason) ... wonder if noidas digging could help there :/
      05:56:16: <noida> oh sweet ill make sure to fix that
      05:57:29: <Capella> yah :) No gecko content for screenshots of our UI / Javascript tests is not the most helpful
      05:59:21: <noida> ok so i think i setup makeText right can you please check: https://gist.github.com/Noitidart/400261f83b1be721a93a#file-_ff-addon-tutorial-jnitoast-js-L25
      06:14:47: <noida> so here he does: https://github.com/cscott/intent-addon/blob/master/lib/main.js#L111
      06:14:56: <noida> i["putExtra(Ljava/lang/String;Ljava/lang/CharSequence;)"+isig].call(i, key, Html.fromHtml(value));
      06:15:03: <noida> so he's using the putExtra method of Toast
      06:15:06: <noida> and it returns i
      06:15:10: <noida> which is an Intent
      06:15:13: <noida> i gathered that from here:
      06:15:27: <noida> http://developer.android.com/reference/android/content/Intent.html#putExtra%28java.lang.String,%20double[]%29
      06:15:50: <rnewman> that looks OK to me, noida
      06:15:57: <rnewman> I haven't run it, so it might be wrong, but it looks good
      06:16:03: <noida> oh sweet
      06:16:08: <noida> im working on make the call right now
      06:16:10: <noida> then ill run too :)
      06:16:18: <rnewman> :)
      06:16:26: <rnewman> I'll be heading to bed when I'm done with this drink
      06:16:38: <noida> ah ok thx i think im getting the hang of this
      06:16:48: <noida> im loooking up the docs based on what was used in jni
      06:16:53: <noida> and your types page is a god send
      06:16:57: <noida> i was baffled by those letters
      06:19:46: <noida> oh last two questions plz
      06:19:49: <noida> whats the V here: https://github.com/mozilla/firefox-for-android-addons/blob/355f9a01464a0794c1084e8fdbab92c58503f49a/snippets/jni.js#L32
      06:19:57: <noida> i cant find it on the types page
      06:20:30: <noida> also he leads off with () instead of just L like i thought he should here: https://github.com/mozilla/firefox-for-android-addons/blob/355f9a01464a0794c1084e8fdbab92c58503f49a/snippets/jni.js#L27
      06:20:46: <noida> { name: "getContext", sig: "()Landroid/content/Context;" },
      06:30:45: <Capella> void?
      06:30:59: <noida> ah ya
      06:31:20: <Capella> http://www.rgagnon.com/javadetails/java-0286.html
      06:31:26: <Capella> "there are two parts...."
      06:32:03: <noida> oh they have V here thx
      06:42:10: <noida> how would i know if makeText should be in array of `static_methods` or just `methods`? based on docs: http://developer.android.com/reference/android/widget/Toast.html#makeText%28android.content.Context,%20int,%20int%29
      06:42:51: <noida> ohhh is the () indicate thats the return type?
      06:43:06: <noida> so ()Landroid/content/Context;I would mean returns context and accepts one argument of int?
      06:45:25: <wesj> noida: arguments appear between the (). you can have one value after the () for the return type
      06:45:38: <wesj> so that would be (I)Landorid/content/Context;
      06:46:12: <noida> thats not how these people are doing :( did we change the jsm?'
      06:46:20: <noida> ohh wait
      06:46:22: <noida> i think they are!
      06:46:36: <wesj> static_methods are methods labeled as static in the java class. they don't need an instance of the class to call them
      06:46:58: <wesj> i.e. Toast.makeText() vs something like (new Toast()).makeText()
      06:47:08: <noida> ahhh
      06:47:15: <noida> that ex made it make sense!
      06:47:23: <noida> so makeText is a static!
      06:47:32: <noida> public static Toast makeText (Context context, int resId, int duration)
      06:47:40: <noida> if it wasnt static would that line be
      06:47:42: <noida> public Toast makeText (Context context, int resId, int duration)
      06:51:09: <wesj> yep
      06:51:16: <noida> ah super cool! thanks!
      06:51:19: <noida> so whats the return of this?
      06:51:24: <noida> makeText returns a Toast class?
      06:51:28: <noida> i mean a Toast object?
      06:52:57: <Capella> Toast fooToast = Toast.makeText( ...
      06:53:11: <wesj> yep. so you'd normally call Toast.makeText().show();
      06:53:17: <noida> ahhh
      06:53:18: <wesj> so show() gets called on the Toast object you created
      06:53:21: <noida> making senes!! thank you!
      06:53:23: <Capella> fooToast.show()
      06:53:45: <noida> thx cap!
      06:54:26: <noida> so in jni to call a method i have to use .call?
      06:54:45: <noida> var text = i["makeText(Landroid/content/Context;Ljava/lang/CharSequence;)"+isig].call(context, 'Hello toast!');
      06:55:43: <wesj> i don't think so...
      06:56:43: <wesj> you'd usually do what i saw you had earlier var Toast = JNI.LoadClass(class_stuff); var t = Toast.makeText(context, "HelloWorld"); t.show();
      06:56:50: <noida> ah!
      06:57:21: <wesj> but after that first JNI.LoadClass stuff Toast.makeText is just a javascript function, so you CAN call it with Toast.makeText.call() or Toast.makeText.apply() even
      06:57:28: <wesj> anything you can do with a normal javascript function
      06:58:35: <noida> ahhh
      06:58:46: <noida> but how come sometimes (lots of times) they do LoadClass without setting it to var?
      06:58:47: <noida> http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js#40
      06:59:51: <rnewman> noida: if you don't have to use the class directly; it just needs to be loaded
      06:59:55: <wesj> i guess we didn't need a reference to the class there
      07:00:07: <wesj> but other methods return a Context, so we wanted to define some methods on what they returned
      07:00:39: <wesj> i.e. geckoAppShell.getContext() returns a Context to you. without loading it, the JNI code would have no idea what that was
      07:01:01: <noida> oo
      07:02:32: <noida> http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js#17
      07:02:34: <noida> in the sig here
      07:02:41: <noida> how come they dont do a +I or something
      07:02:45: <noida> like they do everyewhere else:
      07:03:18: <noida> https://github.com/cscott/intent-addon/blob/master/lib/main.js#L39
      07:04:36: <noida> ah!
      07:04:43: <Capella> thats +Intent ... "Landroid/content/Intent;"
      07:04:43: <noida> the + thing is outside of hte () so its the return type?
      07:04:54: <Capella> js addition
      07:05:03: <noida> so if it doesnt have + anything it has no return?
      07:05:07: <satdav> noida: what time zone you on.
      07:05:20: <noida> moz hq zone :D
      07:05:31: <noida> 10min from mountain view office :P
      07:05:35: <noida> pacific :)
      07:05:52: <wesj> noida: its just a convenience thing some people have done i guess
      07:06:02: <noida> for the treturn type wes?
      07:06:12: <wesj> i.e. rather than rewriting "Landroid/content/Intent;" after every signature they write "+ Intent"
      07:06:15: <satdav> Cool so pt, was looking for someone from Toronto time zone
      07:06:21: <noida> ah
      07:06:35: <wesj> yeah, they could use it anywhere, but they use it for return types a lot
      07:06:43: <noida> ahhh
      07:06:54: <noida> is it ok if i end everything with a semicolon?
      07:07:03: <noida> "(Landroid/content/Context;Ljava/lang/CharSequence;I)"
      07:07:03: <wesj> the other function returns an Int which is just "I" so you don't save much by typing "+ Int"
      07:07:10: <noida> AH!
      07:07:20: <noida> and there is no semicolon after return type?
      07:07:25: <noida> oh wait sometimes they do put it
      07:07:37: <wesj> the semicolons are for classes. so there are basic types, int, long, bool, etc
      07:07:40: <wesj> and they're all just letters
      07:07:54: <noida> Ahhhh holy heck making sense!
      07:08:02: <noida> so if args were int and bool
      07:08:04: <noida> i would just write
      07:08:06: <noida> IZ
      07:08:09: <wesj> but for classes the signature looks like LclassName; (i.e. L - some stuff - semicolor)
      07:08:26: <wesj> err semicolon :)
      07:08:31: <noida> haha
      07:08:33: <satdav> Is it just passed 12 at mozilla hq time zone
      07:08:43: <wesj> satdav: 11
      07:08:43: <noida> 11:04 pm
      07:09:10: <satdav> Ok
      07:09:25: <satdav> wesj: you still pt
      07:09:54: <wesj> satdav: yeah
      07:10:11: <satdav> Also you seen or herd from Michelle recently
      07:10:51: <noida> So how come `org.mozilla.gecko.GeckoAppShell` doesnt have a semi?
      07:10:53: <noida> its a class no?
      07:11:04: <noida> http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js#15
      07:11:30: <Capella> it's a single parm in a list
      07:11:43: <noida> but they use it in LoadClass
      07:12:02: <Capella> as part of the "sig" value?
      07:12:10: <noida> http://mxr.mozilla.org/mozilla-central/source/mobile/android/tests/browser/robocop/testJNI.js#15
      07:12:30: <satdav> Does anyone use android studio
      07:13:27: <Capella> looks like you need a ; after an L return type as a delimeter ... the others are implied stops
      07:13:54: <noida> can you please dumb that down a bit :P
      07:14:42: <Capella> with L you name an object delimeted by ;
      07:14:59: <Capella> in the sig field
      07:15:12: <noida> how come this class isn't L while all others are?
      07:15:23: <noida> heres my latest revision: https://gist.github.com/Noitidart/400261f83b1be721a93a
      07:15:28: <noida> its crashing though :(
      07:17:16: <Capella> { name: "LENGTH_SHORT", sig: SIG.int } probably isn't right
      07:17:17: <Capella> { name: "LENGTH_SHORT", sig: "()" + SIG.int } or something?
      07:17:18: <noida> oh interesting
      07:17:22: <noida> no L or ; here either: https://github.com/mozilla/firefox-for-android-addons/blob/355f9a01464a0794c1084e8fdbab92c58503f49a/snippets/jni.js#L30
      07:17:30: <noida> ahhh
      07:17:33: <noida> thx cap ill test
      07:17:55: <noida> crash :(
      07:18:26: <noida> I didnt define any Constructors? should i do that?
      07:18:29: <wesj> satdav: nope. just some pics on facebook :)
      07:19:20: <noida> http://developer.android.com/reference/android/widget/Toast.html#Toast%28android.content.Context%29
      07:19:29: <noida> it says Toast Constructor must be called before show
      07:22:57: <noida> the types page says L fully-qualified-class ; fully-qualified-class
      07:23:01: <noida> https://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/types.html#wp9502
      07:23:11: <noida> so geckoShell should actually start with L and end with semicolon huh?
      07:23:24: <noida> but when doing loadClass i think it is not required
      07:23:33: <noida> as the bridge adds the L and colon if not found (Im guessing)
      07:24:22: <noida> cap man when defining static_fields he didnt do a "()" + SIG ==> https://github.com/cscott/intent-addon/blob/master/lib/main.js#L31
      07:24:23: <wesj> noida: yeah, i'm not sure either
      07:24:32: <wesj> noida: reading through the bridge code, i don't see it do that
      07:24:42: <noida> oh thx for that check wes
      07:24:52: <wesj> but i think it falls back to a generic Java Object in some cases
      07:24:59: <wesj> so maybe things just happen to keep working
      07:26:20: <Capella> btw ... instead of |[SIG.Context, SIG.CharSequence].join()| just do |SIG.Context + SIG.CharSequence|
      07:27:03: <noida> ah is it better for perf?
      07:27:23: <Capella> ah forgot the "," :)
      07:27:45: <noida> ah yea thats much better for docs anyways
      07:27:55: <Capella> |SIG.Context + "," + SIG.CharSequence|
      07:27:57: <Capella> heh - I like the shorthand ... up to you
      07:28:03: <noida> i like it too
      07:28:04: <noida> https://gist.github.com/Noitidart/a67e7556027889070bb6
      07:28:06: <noida> thats copy paste code
      07:28:28: <noida> if i had L and ; around it here: https://gist.github.com/Noitidart/a67e7556027889070bb6#file-gistfile1-txt-L6
      07:28:29: <noida> it crashes
      07:28:42: <noida> so i think when doing LoadClass it must not have that L or ;
      07:29:17: <noida> ahh
      07:29:22: <noida> this must be what crashes my Toast code
      07:29:23: <noida> testing!
      07:30:10: <Capella> the second parm in the LoadClass() is just a string ... the delimeter is implied at end
      07:30:10: <wesj> heh. i think JNI.jsm does strip the L and ; for you http://mxr.mozilla.org/mozilla-central/source/mobile/android/modules/JNI.jsm#884, but I have a feeling Java doesn't like the periods.
      07:30:56: <noida> ah weird!
      07:31:00: <noida> how come that would crash then :(
      07:31:13: <noida> and if i omitted it, it worked fine
      07:31:59: <noida> crap my Toast still crashes lol
      07:33:07: <noida> here's my updated commit: https://gist.github.com/Noitidart/400261f83b1be721a93a
      07:36:06: <wesj> noida: i would avoid ever using periods in your signatures
      07:36:09: <wesj> always use /
      07:36:35: <wesj> but... i always was confused by this a bit :)
      07:36:35: <noida> oh!
      07:36:37: <noida> testing
      07:37:15: <noida> i think thats what cap was trying to tell me
      07:37:26: <noida> cap man im a noob!! forget about my other ctypes work :P
      07:37:41: <noida> jni's a beast!
      07:38:02: <noida> aw dang still crashed :9
      07:38:05: <wesj> i would also probably guess that the signature for LENGTH_SHORT should just be SIG.int not () + SIG.int (since its not a function)
      07:38:33: <Capella> oops ... mmm
      07:38:37: <wesj> lol. i always debug by just commenting everything out and slowly adding things
      07:38:45: <wesj> which you've done mostly!
      07:38:55: <noida> hahaha
      07:39:06: <noida> fixed that SIG.int and replaced .'s
      07:39:07: <noida> https://gist.github.com/Noitidart/400261f83b1be721a93a
      07:39:10: <noida> still crashed :'(
      07:39:22: <noida> ill try that commenting technique a little harder lol
      07:42:27: <noida> this code doesnt crash
      07:42:28: <noida> https://gist.github.com/Noitidart/400261f83b1be721a93a#file-_ff-addon-tutorial-jnitoast-js-L18-L22
      07:42:32: <noida> the problem is in that makeText
      07:42:43: <noida> let me test and see if this crashes with .'s
      07:42:59: <Capella> JNI.LoadClass(jenv, SIG.Toast.substr(1, SIG.Toast.length - 2) ... is not pretty
      07:43:01: <noida> ah it doesnt crash if i use .'s!
      07:43:06: <noida> i know :(
      07:43:50: <wesj> lol
      07:43:53: <wesj> sorry
      07:44:10: <noida> nooo problem im learning so much here
      07:44:14: <noida> and doing it togather makes it so fun
      07:44:21: <noida> cap never does anything with me!
      07:44:24: <wesj> makeText takes a third parameter, do you need it?
      07:44:27: <noida> so we just had a 3 way
      07:44:38: <noida> ah i must of missed it!
      07:44:40: <noida> let me add it
      07:44:48: <Capella> 'cause you make drunk passes @ me :)
      07:44:57: <wesj> hahah
      07:44:59: <noida> ;) ;) HAHAHAH
      07:45:18: <Capella> ah, those saturday nights in the #introduction channel
      07:45:31: <noida> :D :D :D
      07:45:58: <Capella> :p
      07:46:32: <noida> ohhhhh
      07:46:34: <noida> it doesnt crash!!!
      07:46:40: <noida> it was that arg! o my gosh! so cooool!
      07:46:45: <Capella> \o/ thats a good thing
      07:47:02: <noida> https://gist.github.com/Noitidart/400261f83b1be721a93a
      07:48:19: <Capella> interesting though http://mxr.mozilla.org/mozilla-central/search?string=JNI.LoadClass%28&find=&findi=&filter=^[^\0]*%24&hitlimit=&tree=mozilla-central
      07:48:56: <Capella> JNI.LoadClass(jenv, "org/mozilla/gecko/GeckoNetworkManager"
      07:49:30: <noida> haha
      07:49:50: <noida> would the equivalent of `CharSequence text = "Hello toast!";` be `var text = 'Hello toast!';` correct?
      07:50:15: <Capella> sure
      07:50:35: <noida> sweet testing
      07:51:36: <Capella> get the screenshot working ... robocop needs it ... stupid reftests already have it available :/
      07:52:18: <noida> WORKING BABY!!!!
      07:52:30: <Capella> heh - yay :)
      07:52:34: <noida> https://gist.github.com/Noitidart/400261f83b1be721a93a
      07:52:36: <noida> oooooooweeeee
      07:52:42: <noida> thanks guys!!!
      07:52:49: <noida> that link for V was real helpful!
      07:52:58: <noida> http://www.rgagnon.com/javadetails/java-0286.html
      07:53:09: <noida> wow jni makes sense!!
      07:53:11: <noida> its not that bad!!
      07:53:29: <noida> probably cuz of the bridge though
      07:53:33: <Capella> I love the low level glue ... asm is under-rated
      07:53:42: <noida> oh i didnt get into asm
      07:54:01: <Capella> webasm is going to be awesome
      07:55:22: <wesj> yay!
      07:57:51: <noida> this is so great for the docs seriuosly thx wes and cap
      07:57:57: <noida> wes you were reallll awesome thx!
      07:58:10: <KvasoonX> hello, I've got a question about Fennec for iOS, how far is Fennec for iOS? It's in simillar stage as Fennec for Android? Thanks
      07:59:04: <wesj> KvasoonX: you can pull and build it here https://github.com/mozilla/firefox-ios
      07:59:50: <wesj> KvasoonX: it doesn't have a lot of the features that we have on Android right now though
      07:59:58: <wesj> (but we'll get there eventually)
      08:00:02: <KvasoonX> heh actually I dont have Mac, or it isnt requirement?
      08:00:15: <wesj> i think it is right now
      08:00:40: <wesj> we're hoping to do the 1.0 release in the next month or so
      08:01:21: <KvasoonX> Thanks :]
      08:01:28: <noida> where was org.mozilla.gecko.GeckoAppShell defined in dxr? like how did we know it was org.mozilla.gecko.GeckoAppShell? i need this for the docs :)
      08:01:40: <noida> https://dxr.mozilla.org/mozilla-central/search?q=org.mozilla.gecko.GeckoAppShell&case=true pulls up a buuunch
      08:02:35: <wesj> noida: the actual class is at https://dxr.mozilla.org/mozilla-central/source/mobile/android/base/GeckoAppShell.java
      08:02:50: <noida> thx! :D
      

Rev10

  • Updated Gist filename and description

Rev11

  • Removed getPreferredIconSize method as its unused

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment