MathJax in an Android app

5,648 views
Skip to first unread message

Thomas Leathrum

unread,
Jun 4, 2012, 11:22:23 AM6/4/12
to mathja...@googlegroups.com
I have written an Android app which renders TeX math expressions using MathJax inside the app.  For those with Android devices, here is a link to install the app:

http://cs.jsu.edu/~leathrum/mjapp-src/MathJaxApp.apk

Just point your Android device's browser at the above link, and it will launch the package installer.  You will be asked to approve the app for internet access -- this is an important part of how the app works, it uses MathJax loaded from the CDN rather than a local copy.  The app places the input string into LaTeX display math delimiters automatically, so MathML and ASCIImath input modes are not supported.  Output uses HTML-CSS presentation with the web fonts.

I wrote this initially just as a demonstration that MathJax can be used dynamically inside an Android app, and as such, there isn't really much to the app's code.  I have found it to be pretty handy on my tablet, though, for checking MathJax snippets in HTML documents I am writing, so I am making the app more widely available, starting here.  Please let me know what comments or suggestions you have.  I am preparing the materials needed to post the app on the Google Play store, but there is still plenty of time for me to make changes.

In particular, I am interested in getting some field reports about device support.  I have set the compiler to generate code compatible with Android 2.2 (Froyo) or later, but my test platforms include only a Honeycomb 3.2 tablet and an ICS 4.0 emulator.

The "Example" button rotates through several (currently 7) short MathJax TeX samples.  Links at the bottom point to a few MathJax documentation pages (the links launch a browser).

For those interested in Android development using MathJax, the app source is available from links on my Wordpress blog:

http://cs.jsu.edu/wordpress/?p=464

The key to the dynamic MathJax is to load the scripts with a WebView widget.  Then AJAX calls for the WebView loaded using "javascript:" URLs can modify the math content and queue the Typeset routine just as you would in ordinary JavaScript.

Peter Krautzberger

unread,
Jun 4, 2012, 2:53:55 PM6/4/12
to mathja...@googlegroups.com
Hi Tom,

Very nice! Could you release the app under Apache license? I want to create a repository with examples such as this and that way we can make your app part of the MathJax repositories on Github.

Btw, have you tried to include a copy of MathJax in the app?

Peter.

Peter Krautzberger

unread,
Jun 4, 2012, 10:14:16 PM6/4/12
to mathja...@googlegroups.com
FYI, I've created a new repository https://github.com/mathjax/MathJax-examples for example apps etc.

Peter.

Murray

unread,
Jun 5, 2012, 4:38:09 AM6/5/12
to mathja...@googlegroups.com
Hi Thomas

It worked fine in a Samsung Ace phone.using Froyo 2.2.1.

When cycling through the Examples, I could see remnants on the right of the screen from a previous example. For example, one of the left brackets in the \int _a^b f(x)\ dx... example was on the far right of the screen and stayed there for the next few examples until something fairly lengthy did a complete screen re-draw.

Hope that makes sense.

Thanks for the app.

Murray

Murray

unread,
Jun 5, 2012, 5:27:34 AM6/5/12
to mathja...@googlegroups.com
Here's a screen shot of what I was on about:

d^3p

unread,
Jun 5, 2012, 12:19:40 PM6/5/12
to mathja...@googlegroups.com
No problem in Xoom using ICS 4.0.4.

Please check out my free app. Here is the link: https://play.google.com/store/apps/details?id=com.jds.specialproducts

d^3p

Peter Krautzberger

unread,
Jun 5, 2012, 2:23:52 PM6/5/12
to mathja...@googlegroups.com
Also works well on Galaxy Nexus / ICS 4.0.2

Thomas Leathrum

unread,
Jun 6, 2012, 12:29:52 PM6/6/12
to mathja...@googlegroups.com
Thanks all for the platform reports -- I feel better now about my compiler settings.

@Murray -- I'm not seeing that un-erased bracket in my tests, maybe it's an artifact of Froyo's WebView implementation?  I'm pretty sure that the un-erased bracket comes from the wide example showing the Fundamental Theorem -- does that example scroll side-to-side for you in Froyo?  It did for me in my ICS emulator set on a narrow window view.  I'm not sure what to suggest.  I'm afraid if I try to fix in in the code, I'll break it in Honeycomb and ICS.

@Peter -- re: local copy of MathJax, yes I thought about doing that, but I was actually pretty dumbstruck when I realized that it worked when running MJ off the CDN, so I thought it was a feature worth exploiting.  It certainly makes for a much smaller APK download (less than 50Kb without the local copy).  I have not tried the local copy approach yet, but I am pretty sure I know how to do it -- the only issue would be whether it will encounter same-domain security problems akin to Firefox's problems with "file:" URLs.

@Peter -- re: license, I am planning on keeping the app open-source, so I do want a public license.  For MJ purposes, is there a reason to prefer Apache over GPL, or are both acceptable?

Peter Krautzberger

unread,
Jun 6, 2012, 1:13:52 PM6/6/12
to mathja...@googlegroups.com
@Tom 

You shouldn't run into same-origin problems, I think. Android's browser is webkit-based and is more flexilbe than Firefox. You could slim it down all the way to 1.4MB unpacked if you wanted (like Davide did for Readium). 

Apache is a permissive license, i.e., not a copyleft license. That way more people can build on your app (which is why MathJax uses it). For the example repository, this wouldn't be critical though (but slightly easier).

Peter.

Thomas Leathrum

unread,
Jun 7, 2012, 5:47:35 PM6/7/12
to mathja...@googlegroups.com
@Peter -- re: license, that makes sense to me, Apache it is.  I have applied the Notice to all of the original source files and recompiled the APK with the Notice and License texts in the "assets" directory.  I added a bit of extra information in the Notice file indicating licenses for other libraries and tools used:  Eclipse (which also uses the Apache license) and Android SDK (which includes a "no interest" clause) -- so everything is clear for MJ.  Links above have not changed.


micheal...@gmail.com

unread,
Jun 15, 2012, 2:46:01 AM6/15/12
to mathja...@googlegroups.com
hi Thomas

is there any way that you know of, to run mathjax while offline to render equations? it seems that in Android 4.0 local javascript files are not run...

we want to render math equations while not connected to the internet using stored HTML and ASCIIMathML content.

is this possible?

thanks for listening!

Micheal


On Monday, 4 June 2012 23:22:23 UTC+8, Thomas Leathrum wrote:

Davide P. Cervone

unread,
Jun 15, 2012, 6:28:36 AM6/15/12
to mathja...@googlegroups.com
There is a suggestion at


for the security issue with local javascript in Android 4.0, but I don't know if it works or not.

Davide

makra...@gmail.com

unread,
Dec 10, 2012, 4:28:23 AM12/10/12
to mathja...@googlegroups.com
Hello, 

Your app works like a charm, I am trying to render MathML expression 
I did following changes for MathML but dosent work, would you please suggest What I am missing ?

w.loadDataWithBaseURL("http://bar", "<script type='text/x-mathjax-config'>" + "MathJax.Hub.Config({ "

+ "showMathMenu: true, " + "jax: ['input/MathML','output/HTML-CSS'], "

+ "extensions: ['toMathML.js'], " + "TeX: { extensions: ['AMSmath.js','AMSsymbols.js',"

+ "'noErrors.js','noUndefined.js'] } " + "});</script>" + "<script type='text/javascript' "

+ "src='file:///android_asset/MathJax/MathJax.js'" + "></script><span id='math'></span>", "text/html",

"utf-8", "");

Davide Cervone

unread,
Dec 10, 2012, 6:20:27 AM12/10/12
to mathja...@googlegroups.com
you probably want "mml2jax.js" rather than "toMathML.js" (which is what is used to produce the MathML output in the Show Math As... menu).  You also don't need to TeX section of the configuration since you aren't using TeX input.

Davide

Thomas Leathrum

unread,
Dec 10, 2012, 3:10:30 PM12/10/12
to mathja...@googlegroups.com
I'm not sure the mml2jax.js extension is necessary if the input jax is set to MathML, but it certainly won't hurt anything.  You will, however, have to put the MathML input jax file back into the app's assets directory -- I took it out because I was focusing on TeX input.  Also, in the onClick() method, I automatically add LaTeX math delimiters \[...\] (look for "innerHTML='\\\\[...\\\\]' " -- all of those extra backslashes are required to deal with JavaScript escapes).  You will need to remove these and consider replacing them with something like <math>...</math> to enclose the MathML.

Davide Cervone

unread,
Dec 10, 2012, 5:45:39 PM12/10/12
to mathja...@googlegroups.com
If you aren't putting the <math> tags inside MathJax <script> tags, then you will need the mml2jax.js extension (which does that for you).

Davide

Thomas Leathrum

unread,
Dec 11, 2012, 12:52:02 AM12/11/12
to mathja...@googlegroups.com
I put together a MathML-based standalone version of the app for you to check out -- here is a URL to it on github.com:

https://github.com/leathrum/android-apps/tree/master/MathJaxApp/mml-full

You should be able to install the APK and go.  I still need to clean it up and fancy it up some -- for example, it doesn't have the MathJax icon, it only has one MathML example to show with the "Example" button, the MathML for the example isn't indented, and there is no README in the github directory.  But it should be enough in short term to show you how the code works.  I did follow Davide's suggestion of using mml2jax.js in order to avoid having to code in the MJ <script> tags.  I did, however, hard-code the <math> tags (with the xmlns attribute) and <mstyle displaystyle="true">, so it behaves and looks very much like the TeX version.  I tested it in Android 4.0 ICS.  It uses a local, scaled-down copy of MJ2.1.

makra...@gmail.com

unread,
Dec 11, 2012, 2:47:06 AM12/11/12
to mathja...@googlegroups.com
Yes I have modified code successfully for MathML and removed but now When I am trying load Webview in onCreate method

my code in onCreate(){

setContentView(R.layout.activity_main);

 WebView w = (WebView) findViewById(R.id.webView);

w.getSettings().setJavaScriptEnabled(true);

w.loadDataWithBaseURL("Loading of MathJax");

 w.loadUrl("javascript:document.getElementById('math').innerHTML='" + mathMLData + "';");

 w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);"); 

it dosent work. but IF I put same code in any Listener then it redens successfully, it dosent render mathML in onCreate() method 

my onClick code 

if (v == findViewById(R.id.button2)) {

 WebView w = (WebView) findViewById(R.id.webView);

    w.loadUrl("javascript:document.getElementById('math').innerHTML='"mathMLData1 + "';");

    w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");

}


if
 (v == findViewById(R.id.button1)) {

 WebView w = (WebView) findViewById(R.id.webView);

    w.loadUrl("javascript:document.getElementById('math').innerHTML='" + mathMLData2 + "';");

    w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");

}


It Works perfectly fine in onCilck method but it doesn't work in OnCreate, not getting why ? 

Thomas Leathrum

unread,
Dec 11, 2012, 8:51:48 AM12/11/12
to mathja...@googlegroups.com, makra...@gmail.com
Ah -- now I see what you are trying to do.  I'm not sure yet what the answer is, I will need to try a few experiments, but I suspect that there is a timing issue here, as in you may be trying to inject the MathML code before the  WebView is ready to display and run scripts.  Give me some time to try this out in my code and I will post results.

makra...@gmail.com

unread,
Dec 12, 2012, 2:09:46 AM12/12/12
to mathja...@googlegroups.com, makra...@gmail.com
Yes you are correct there is timing issue, I have added following code and its works fine,

final Handler handler = new Handler();

Timer t = new Timer();

t.schedule(new TimerTask() {

    @Override

    public void run() {

handler.post(new Runnable() {

    @Override

    public void run() {

w.loadUrl("javascript:document.getElementById('math').innerHTML='" + MathMLData + "';");

w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");

    }

});

    }

}, 800);

Thomas Leathrum

unread,
Dec 12, 2012, 3:28:54 PM12/12/12
to mathja...@googlegroups.com, makra...@gmail.com
I was actually not able to reproduce the problem you were having -- for me, putting the MathML into the HTML loaded in the onCreate() method works.  In particular, in onCreate(), I changed the call to w.loadDataWithBaseURL() to read as follows:


        w.loadDataWithBaseURL("http://bar", "<script type='text/x-mathjax-config'>"
                              +"MathJax.Hub.Config({ "
                              +"showMathMenu: false, "

                              +"jax: ['input/MathML','output/HTML-CSS'], "
                              +"extensions: ['mml2jax.js'], "
                              +"TeX: { extensions: ['noErrors.js','noUndefined.js'] }, "

                              +"});</script>"
                              +"<script type='text/javascript' "
                              +"src='file:///android_asset/MathJax/MathJax.js'"
                              +"></script><span id='math'>"
                              +"<math xmlns=\"http://www.w3.org/1998/Math/MathML\">"
                              +"<mstyle displaystyle=\"true\">"
                               +getExample(0)
                              +"</mstyle></math>"       
                              +"</span>","text/html","utf-8","");

Note that getExample(0) just returns the first entry in the array of MathML examples in the strings.xml file.  For me, this works -- the expression displays when the app loads, before clicking any buttons.  The only thing I can suggest that we might be doing differently is to suggest that you make sure you have your <math>...</math> tags in place here correctly.

In any case, even if you are encountering a timing issue, the approach you took to fixing it would tend to be rather fragile -- you just make sure you have an 800 millisecond delay before you inject the Javascript, but that delay could expire before you want if there are other background processes taking up time.  It could also be a noticeable performance issue.

hiteshc...@gmail.com

unread,
Jul 28, 2013, 5:37:23 PM7/28/13
to mathja...@googlegroups.com
Has anyone complied it in Android studio 0.2.2. It's failing with many issues.  I fixed few but still throwing error at 

java: package R does not exist

Dayal Purohit

unread,
Jul 29, 2013, 3:47:28 PM7/29/13
to mathja...@googlegroups.com, hiteshc...@gmail.com
I don't use Android Studio, may be some day I will switch.

The problem you describe also happens in Eclipse and in any Android App development. When that happens, I usually clean the project and R is automatically rebuilt.

d^3p

micheled...@gmail.com

unread,
Sep 11, 2013, 5:29:27 AM9/11/13
to mathja...@googlegroups.com, hiteshc...@gmail.com
Hi and thanks for the MathJax Android app!

I am trying to use it to port my website to an Android app, and I face the following problem.

In my website, I used MathJax as follows.

        <script type="text/x-mathjax-config">
            MathJax.Hub.Config({
            extensions: ["tex2jax.js"],
            jax: ["input/TeX","output/HTML-CSS"],
            tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]}
            });
        </script>
        <script type="text/javascript" src="mathjax/MathJax.js"></script>

I want to point out that I used inlineMath expressions, so for example I have something like that.
Bla bla here comes the math expression \\(\\frac{1}{2} \\rho = 0,125\\) bla bla my text goes on and on and on...

I am not able to use inline expression in your Android app (yet).

Any help would be greatly appreciated, thanks a lot! 

Davide P. Cervone

unread,
Sep 11, 2013, 3:19:54 PM9/11/13
to mathja...@googlegroups.com, hiteshc...@gmail.com
I want to point out that I used inlineMath expressions, so for example I have something like that.
Bla bla here comes the math expression \\(\\frac{1}{2} \\rho = 0,125\\) bla bla my text goes on and on and on...

Note that the text in the page should be just   \(\frac{1}{2} \rho = 0,125\)   without the double backslashes. I'm not sure if you showed double ones because you were giving the contents of a string constant in JavaScript, or if you actually had double backslashes in the text on your HTML page.  The reason they are doubled in the Config() call is that they are inside Javascript strings, where the backslash is used as an escape character (for things like \n and \u00A), so to get an actual (single) backslash in the resulting string, you need to escape it, as "\\".  So ['\\(','\\)'] is an array containing two strings, and each string contains a single backslash followed by an open or close parenthesis.

Hope that was the issue.

Davide

micheled...@gmail.com

unread,
Sep 13, 2013, 9:46:00 AM9/13/13
to mathja...@googlegroups.com, hiteshc...@gmail.com, dp...@union.edu
I wrote the String that I want to display, exactly as it is stored in my SQlite database.
I understood that my String is already double escaped (I stored in this way in my database indeed) so I did not need to use again the doubleEscape() function.

However, the webview I use to display my math content, sometimes works, sometimes does not!
It only shows 
unknown chromium error -6
when it doesn't work, and in this case either it doesn't load the javascript or the view starts flickering or other weird things happen... very difficult to debug!

Maybe there is some confict between my Android app code and the one from the MathJax app, but I haven't been able to fix the issue yet.

If you have any idea, I will be very grateful to hear it! :)

Thanks.

Peter Krautzberger

unread,
Sep 15, 2013, 11:51:06 PM9/15/13
to mathja...@googlegroups.com, hiteshc...@gmail.com, Davide P. Cervone
Hi,

It might be a good idea to post this on a forum with more Android developers (e.g. StackOverflow) and cross post the link here.

Peter.


--
You received this message because you are subscribed to the Google Groups "MathJax Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mathjax-user...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Dayal Purohit

unread,
Sep 16, 2013, 6:50:49 PM9/16/13
to mathja...@googlegroups.com, hiteshc...@gmail.com, dp...@union.edu, micheled...@gmail.com
depending on where the string is and where it is going and how it going, you may have to escape it more than once may be \\frac or \\\\frac or \\\\\\frac

d^3p

micheled...@gmail.com

unread,
Sep 17, 2013, 4:42:03 AM9/17/13
to mathja...@googlegroups.com, hiteshc...@gmail.com, dp...@union.edu, micheled...@gmail.com
Thanks for your advice, here are are my latest findings.

First of all, running the original app (https://github.com/leathrum/android-apps/tree/master/MathJaxApp/full) I get the following errors that I have in my project too.
E/cutils-trace(3870): Error opening trace file: No such file or directory (2)
D/TilesManager(3870): Starting TG #0, 0x2a2760f0
D/chromium(3870): Unknown chromium error: -6
Hence I can state these errors are not caused by my code, but by the original code linked on GitHub.

However, the original code works, because these errors appears on the onCreate function, but then clicking on the button that displays and renders the formula in the webview works perfectly.

What does not work for me, is loading the content (e.g. my formula text) directly in the onCreate method
I saw someone posted above that he had a similar problem which was solved setting a delay of 800 milliseconds, but I am hoping there's a better solution... 

Basically, the following code works only if you put it in the onClick() function, but does not work if you put in the onCreate(), meaning it does not show anything because it probably tries to load the text ("myFormula" in the example below) before the <span> element with id "math" is created (my guess).
w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
       +doubleEscapeTeX(myFormula)
+"\\\\]';");
w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");

Of course, I need to put my formula in the onCreate method, because I want to display some text in the webview immediately, i.e. I do not want any button such as "Click me to see the text".

Anyone has any idea how to solve that?

Tx a lot for your kind attention.

Dayal Purohit

unread,
Sep 17, 2013, 3:03:25 PM9/17/13
to mathja...@googlegroups.com, hiteshc...@gmail.com, dp...@union.edu, micheled...@gmail.com
perhaps you have not enabled javascript for the webview. get the pointer to webview, then access the websettings of the webview, then using the websettings to enable javascript for the webview.

d^3p

[.::MDT::.]

unread,
Sep 18, 2013, 3:05:35 AM9/18/13
to Dayal Purohit, mathja...@googlegroups.com, hiteshc...@gmail.com, dp...@union.edu
Thanks for your advice, but Javascript was enabled.

Apparently, I managed to find a workaround by using a WebViewClient and the onPageFinished method (althogh the previously mentioned error remains, the text is displayed and the formula is rendered).

     w.setWebViewClient(new WebViewClient() {  
       @Override  
       public void onPageFinished(WebView view, String url)  
       {  
                        w.loadUrl("javascript:document.getElementById('math').innerHTML='\\\\["
        +doubleEscapeTeX(myFormula)
+"\\\\]';");
w.loadUrl("javascript:MathJax.Hub.Queue(['Typeset',MathJax.Hub]);");
       }  
    });

Thanks.

Dayal Purohit

unread,
Sep 18, 2013, 4:35:04 PM9/18/13
to mathja...@googlegroups.com, Dayal Purohit, hiteshc...@gmail.com, dp...@union.edu, micheled...@gmail.com
yes of course and that too. you may also want to override shouldOverrideUrlLoading(WebView view, String url) to prevent links to open in browser instead of in the webview.

d^3p

Elia Immanuel Auer

unread,
Apr 7, 2024, 9:57:24 AM (9 days ago) Apr 7
to MathJax Users
Hello,

The provided link http://cs.jsu.edu/~leathrum/mjapp-src/MathJaxApp.apk appears to be dead now. Is there any current alternative? 

Best Regards,

Elia Immanuel Auer

Reply all
Reply to author
Forward
0 new messages