Few days back, we were facing problem establishing communication between a Webview control and a Titanium UI or vice versa.

We were integrating Facebook authentication in our Titanium mobile app using Titanium Facebook mobule where we stumbled upon this issue. We wanted to trigger FB Auth Titanium module specific code on click of an HTML Login button tied with a jQuery click event. The FB auth module checks if Facebook mobile app is installed on the device and opens this mobile app for authentication otherwise it opens the browser window popup and redirects to Facebook site to authenticate. This is very neat and important feature we wanted in our mobile app.

I posted this issue, article and code on Titanium Appcelerator community here. We also found the solution and posted the answer on same article.

When we call this fb module code var fb = require('facebook'); in our custom javascript file, say fb-auth.js (which has jQuery code) then it was not working. Whereas if we call same code in app.js, which is Titanium view js code, then it was working fine.

We wanted to establish a connect between the web view and Titanium. We found the solution on this Titanium Appcelerator article here. So ideally we can use Ti.App.addEventListener to bind or link the events between Titanium and WebView and then Ti.App.fireEvent to execute it. Here are two quick steps with code.

  1. Write this code in your Titanium app.js file so that we can bind a listener i.e. callback method.

    Ti.App.addEventListener('fromwebview', function(data) {
    fb.authorize();
    });

  2. Execute i.e. fire method fromwebview. For now, write this in your index.html

fb-btn is a Facebook login button in our App UI. We are binding fromwebview to onmousedown event.

Edits from Rohan Pujari with further details as follows ... for both Android and iOS platforms.

fireEvent and addEventListner worked fine on Android, but was not working on iOS devices. If we fired event from web view (HTML, js code) and added addEventListner in app.js file then everything was working fine on both Android and iOS device. But when we wanted to fire event from Titanium code and add a listener for it in our web view then it wasn't working for iOS. This was strange and we were not able to figure out the exact issue. But my guess is it has something to do with how Webview is loaded on iOS devices.

Little bit of research lead us to another solution which allowed us to call our javascript code in Titanium app.js file.
We can use evalJs function on Webview created using Ti.UI.createWebView method. evalJs takes one argument as a string. We can pass all javascript code that we want to run in context of web view as an argument to this function. But the solution raised a question that "We have not created webView manually. Is it already created somewhere or do we have to create it?"

Soon we figured out it was created inside ui/ApplicationWindow.js file. But the ApplicationWindow() function which was exported didn't return WebView. We just wanted the the ApplicationWindow() to return WebView along with the window object that it used to return earlier. Just adding these two lines at the end of ApplicationWindow() function did the trick.

returnVal = [self, webView];
return returnVal;

Now back to the main work. It was now just a matter of passing all javascript code as a parameter to evalJs function. Here is the large code base, on which we spent lot of time to write and rectify :) (sarcasm alert!!).

fb.addEventListener("login", function(e) {
  if (e.success) {
    webView.evalJS("Auth.closeLoginBox()");
    webView.evalJS("FbAuth.afterLoginCallBack('" + fb.accessToken + "')");
  } else {
    webView.evalJS("Auth.showLoginFailedMessage()");
  }
});

Auth.closeLoginBox(), FbAuth.afterLoginCallBack() and Auth.showLoginFailedMessage() are javascript functions that we want to call in web view context. These are the functions that we have written for the web app and are not in scope of Titanium code. Using evalJs we can run any javascript code in web view context.