Saturday, September 24, 2011

Undefined symbol "_OBJC_CLASS_$_GTMOAuth2ViewControllerTouch"

Google's developer documentation for GData Client for iPhone/ObjC seems outdated - I followed the instructions to build the static lib to the letter (Well.. I trust google!) and was stuck for a good few hours with the below error with OAuth classes missing from the static lib while doing release build:


Undefined symbols for architecture armv6:
  "_OBJC_CLASS_$_GTMOAuth2ViewControllerTouch", referenced from:
      objc-class-ref in xxx.o
ld: symbol(s) not found for architecture armv6
collect2: ld returned 1 exit status


Turns out the the "-DGDATA_INCLUDE_OAUTH2=1" C Flag  specified in the Removing Unneeded code section of the instruction is incorrect. It should be "-DGTM_INCLUDE_OAUTH2=1" for the OAuth classes to be linked correctly because thats what is coded inside the OAuth classes! Looks like someone updated the code but forgot to update the documentation.

I have logged an issue - hopefully someone will update the documentation so others don't run into the same issue.
(PS: Hey google, I need me lost hours back!)



Friday, January 14, 2011

Android WebView Proxy setting




Android webview is shaky at best - starting from missing root certificates, weird UI display issues like double text boxes and the most shaky of all - the connectivity itself. Apparently the webkit engine connectivity breaks very frequently with some(slow?) networks. Same issue exist in the andorid web browser application as well as webview reuses the same native browser implementation.
In some cases, the culprit is a slow proxy setup by the network provider by default. Bypassing the proxy could potentially fix that issue, but unfortunately there are no direct APIs to do that programatically, (WebView.enablePlatformNotifications(); require the user to manually enter proxy settings) so the below hack using reflection. The idea is to reset the proxyHost field in the android.net.http.RequestQueue instance within the Network object, so the WebKit engine finds it and sends the request accordingly. Code below.  (Warning: code below uses private APIs)

import android.content.Context;
import org.apache.http.HttpHost;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * Utility class for setting WebKit proxy used by Android WebView
 *
 */
public class ProxySettings {

    /**
     * Override WebKit Proxy settings
     *
     * @param ctx Android ApplicationContext
     * @param host
     * @param port
     * @return  true if Proxy was successfully set
     */
    public static boolean setProxy(Context ctx, String host, int port) {
        boolean ret = false;
        try {
            Object requestQueueObject = getRequestQueue(ctx);
            if (requestQueueObject != null) {
                //Create Proxy config object and set it into request Q
                HttpHost httpHost = new HttpHost(host, port, "http");
                setDeclaredField(requestQueueObject, "mProxyHost", httpHost);
                ret = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    public static void resetProxy(Context ctx) throws Exception {
        Object requestQueueObject = getRequestQueue(ctx);
        if (requestQueueObject != null) {
            setDeclaredField(requestQueueObject, "mProxyHost", null);
        }
    }

    public static Object getRequestQueue(Context ctx) throws Exception {
        Object ret = null;
        Class networkClass = Class.forName("android.webkit.Network");
        if (networkClass != null) {
            Object networkObj = invokeMethod(networkClass, "getInstance", new Object[]{ctx}, Context.class);
            if (networkObj != null) {
                ret = getDeclaredField(networkObj, "mRequestQueue");
            }
        }
        return ret;
    }

    private static Object getDeclaredField(Object obj, String name)
            throws SecurityException, NoSuchFieldException,
            IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        Object out = f.get(obj);
        //System.out.println(obj.getClass().getName() + "." + name + " = "+ out);
        return out;
    }

    private static void setDeclaredField(Object obj, String name, Object value)
            throws SecurityException, NoSuchFieldException,
            IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        f.set(obj, value);
    }

    private static Object invokeMethod(Object object, String methodName, Object[] params, Class... types) throws Exception {
        Object out = null;
        Class c = object instanceof Class ? (Class) object : object.getClass();
        if (types != null) {
            Method method = c.getMethod(methodName, types);
            out = method.invoke(object, params);
        } else {
            Method method = c.getMethod(methodName);
            out = method.invoke(object);
        }
        //System.out.println(object.getClass().getName() + "." + methodName + "() = "+ out);
        return out;
    }
}

Tuesday, May 22, 2007

We need an E4X like XML parser for Java


So we could replace the ugly code blocks like


/*Get the value of attribute "id" of the first "account" element in the document */
NodeList nodes = doc.getElementsByTagName("account")
Element account = (Element)nodes.item(0);
String id = account.getAttribute("id");

with something like

String id = doc.account[0].id;

Wouldn't that be cool?! Better than DOM, SAX, StaX or even XPath to some extent from a usability perspective. But it looks like this ease of use is reserved exclusively for the javascript developers for now :( .. Btw it looks like you can already do this in Ruby using REXML as explained in this excellent article.

Hope rest of the programming world would catch up soon...

Using Google Maps + GPS on Cingular 8125



Unlike most mobile mapping apps, Google maps app doesnt seem to provide an option to manually configure the GPS port (especially since there is no integrated GPS on 8125 and have to use an external bluetooh GPS module instead) and seem to be depending on the system GPS app to grab the info. Cingular 8125 comes with the GPS app (Start -> Settings -> System -> GPS) disabled by default. So if you want to GPS enable your Google maps, you must "unhide/enable" the GPS system app via a Registry hack. There are plenty of sites out there with the instructions, but the one at the official Windows mobile team blog seems to be most reliable and less confusing from my experience.
Just follow the instructions on the link above and you should be good - I was up and running in no time with my Belkin GPS module once I made these changes. I used the "Total Commander Registry Editor" (link available here) to edit my registry settings.

Btw I like Google maps app better than any other apps I've used before. First of all its the exact same UI and maps that you are used to on your desktop + the power of google local. Moreover you always get the latest info since this works online instead of pre-downloaded maps etc. And even though I haven't tried it out fully, the live traffic info option looks pretty cool as well.

Thursday, April 19, 2007

Why "oh-just-switch-the-css" dont work for creating mobile sites



   Well why not? With proper use of CSS, the page source itself is just the text content sans formatting so should be good for the little browsers right? Not exactly and here's why..

1. The needs of a mobile site user are *different* from that of a web user - nobody wants to see the same info they see on a regular web page on their mobile devices. Rather than trying to replicate what is on the web, mobile sites should try and address the needs that are specific to a mobile user - access to specific pieces of info, ability to easily navigate and perform critical actions etc. For example, the mobile site of web mail application would allow registered users to check their mails, Vs allowing new users to register via mobile site.

2. Website content is usually designed for the regular web page size (1024X768) which when displayed on mobile devices - whether PDAs (~320X~240), BlackBerrys (~240X~260), media phones (~220X~180) and other regular phones (~100X~100) - either gets mangled or looses visibility and context and may require considerable scrolling - both horizontal and vertical - to be visible. Another usability consideration is the user input - anything that needs typing should either be replaced or complemented with other alternatives.

3. Mobile devices are extremely resource constrained. Everything including CPU, power, memory and bandwidth (unless you have one of those all-you-can-eat plans) are usually at a premium. So by flooding the mobile device with regular page content, you are not only wasting costly mobile bandwidth, but there is a pretty good chance that you might be overloading the device resulting in unexpected behaviour (freeze? hang?), thereby permanently loosing a "mobile site" user, to say the least.

4. Mobile web technical standards are different from regular web. In fact there are multiple standards in the mobile world and depending on the carrier network and device/browser combination it varies from WAP and WML to HTTP and XHTML-MP with a number of others in between. However one thing that is common across these various standards is that none of them are HTML compliant - which means the chances of your regular web page, or even a reduced version of the same for that matter, getting displayed properly on a mobile device is slim to none. Not to mention the mobile specific issues like the WAP gap (for secure sites) and the latest .mobi TLD restrictions and standards that need to be addressed before the site is launched. Another major factor is the device variations - for example the cookie and Java script support is not uniform across all devices - so if your web site depends heavily on cookies or is AJAX based, or Flash for that matter, your site cannot be mobile "enabled" for sure. And last but not the least.. no popups on my mobile phone please ;)

   A full list of Mobile site issues, guidelines and best practices can be found at the W3C site

Tuesday, March 13, 2007

java.lang.OutOfMemoryError


               Out of memory errors can be pretty tough to crack - especially on high volume applications. The main problem is the lack of tools that work well under heavy loads. Most commercially available tools that works nicely in development fails miserably under high load in the production environments. Unfortunately toughest of the OOMs show up only under production loads; that too usually over a period of time, thus making it next to impossible to reproduce them with the usual load/stress tests. One of the reasons why the commercial tools don't work very well under heavy loads is because they are extremely intrusive. This affects the JVM performance so much that the server CPU usually hits the wall the moment you turn on production traffic. The usual debugging mechanisms, such as rigorous code reviews looking for possible memory leaks and concurrency/performance issues, analysing access logs with error/application logs and verbosegc output, secluding suspect applications into separate JVMs etc helps, and should be sufficient to uncover the culprit code in most cases, but not always!

               So what do you do when everything else fails?! Well.. welcome to the world of the amazing JVMPI/JVMTI APIs. Using JVMPI it is possible to put hooks into JVM to do things that are normally not possible in Java - things such as profiling Java heap, generating object allocation stacktraces etc. This extremely helpful information from the deep insides of the JVM is usually more than sufficient to crack the toughest of the memory leaks. The most important thing here is, unlike the commercial tools which are usually catch all (ie., track everything that happens inside the JVM) you get to pick and choose the specific events that you are interested in. For eg, you can tell JVM to notify only when an object of a particular type or size is created. Even more importantly, you get the ability to generate this information only when you want it. This really is the key to make this work in production environments - the fact that you can programmatically activate/deactivate the tool - to take periodic snap shots of the JVM heap or get allocation stacktraces for a single request etc. The trick is to implement an easily accessible switch that allows to enable/disable the JVMPI module as and when needed - could be as simple as a simple JSP page running in the suspect VM that hooks into the JVMPI module via JNI.

               Sounds interesting and ready for a deep dive? Pl refer to the sample JVMPI utility at http://virtualmachine.de/ and the official JVM PI site.

Thursday, May 11, 2006

The cell phone is tomorrow's desktop!!!





Nope I didnt say it - Father of Java, James Gosling himself, did! Read full article here