Tuesday, September 25, 2012

Cordova (Phonegap) 2.0 In Android 4.1 Jelly Bean XMLHttpRequest Could not Load Error

Hello,

This is short and quick blog on cordova and android Jalley Bean issue. Have you ever encountered error "XMLHttpRequest Could not Load" while working with Android 4.1 Jalley Bean? Complete error is XMLHttpRequest Could not Load, origin null is not supported.

First when I get this error, I thought it's a cross domain issue, but it's not. When you are using cordova all your JavaScripts are loaded by file:/// protocol. So it really does not matter if we use Ajax or JsonP request. Because there is nothing like domain here. So what really is the issue?

While debugging for this error I noticed in my chrome developer tools that, it's trying to fire an XMLHttpRequest on my local machine and that XMLHttpRequest was initiated by some cordova functions. and that was using localhost url which does not exists. So it was breaking the whole app.

How to get rid of this? While debugging I found that this XMLHttpRequest was initiated by polling function of cordova. Cordova has polling mechanism to get response from native API calls. In my app, there wasn't any native API call so I disabled the polling. Find the following line in your cordova file.

UsePolling:true,

and set it to false as follow.

UsePolling:false,

That's it and there will not error on XMLHttpRequest.

Hope this helps you.

Thursday, September 13, 2012

Sencha Touch - Add callback function to animateActiveItem

Hello,

Recently I was working on a sencha touch project and faced an interesting issue. There was a requirement to adjust the layout after animation is completed. When we do animateActiveItem, you might not have noticed this but animateActiveItem is asynchronous. By default sencha touch has animation duration of 250ms. So  when you write following statement.

this.getMain().animateActiveItem(item,{ type: 'slide', direction: 'right'});
this.getMain().query('#element').hide();

You will notice that your element is hidden before animation is completed. You may increase the duration to see this.


this.getMain().animateActiveItem(item,{ type: 'slide', direction: 'right', duration:2000});
this.getMain().query('#element').hide();


So sometimes you might have annoying effects like, some of your UI jumps. To avoid this and have smooth transition, callback is necessary so UI changes can be adjusted after animation is completed. So how to do that? Here is the trick

Override animateActiveItem function of Ext.container


Ext.override(Ext.Container, {
    animateActiveItem: function(activeItem, animation, callback) {
        var layout = this.getLayout(),
            defaultAnimation;
     
        if (this.activeItemAnimation) {
            this.activeItemAnimation.destroy();
        }
        this.activeItemAnimation = animation = new Ext.fx.layout.Card(animation);
        if (animation && layout.isCard) {          
            animation.setLayout(layout);
            defaultAnimation = layout.getAnimation();          
            if (defaultAnimation) {
                defaultAnimation.disable();
                animation.on('animationend', function() {                  
                    defaultAnimation.enable();
                    animation.destroy();

                    if(callback){
                          callback();  
                    }
                }, this);
            }else{
                animation.on('animationend', function() {                  
                    animation.destroy();
                    if(callback){
                          callback();  
                    }
                }, this);
            }
        }
        return this.setActiveItem(activeItem);
    }
});

See the following code carefully.


if(callback){
     callback();  
}

I have added callback function as a parameter in method and that will be invoked when application end. I added this in both if and else part so it will be invoked if you have specified the animation or you are using default animation.

Now your animateActiveItem function call is changed. See the code below.

this.getMain().animateActiveItem(item,{ type: 'slide', direction: 'right', duration:2000},function(){
//your callback function code.
});

See the last parameter, that is your callback function.

Hope this posts helps you.

Saturday, September 1, 2012

Send HTTP Request and retrive HTTP response in iPhone, iPad Application

Hello,

Recently I was working on an iPhone application where requirement was to send HTTP request and retrieve the response. This was not a JSON or restful web service. Checkout the following code.


 NSMutableString* url = [NSMutableString string];
    [url appendString:@"http://www.example.com"];
    NSURLRequest *theRequest=[NSURLRequest requestWithURL:[NSURL URLWithString:url]
                                              cachePolicy:NSURLRequestUseProtocolCachePolicy
                                          timeoutInterval:60.0];
    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    if (theConnection) {
        
        
    } else {
        UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Failed" message:@"Check your networking configuration." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alertView show];
    }

Above code will initiate the connection. If it's successful it will go in if part else it will go in else part. On successful connection we have to retrive the data so we will add few delegates functions for it.

- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {
    NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
       if ([httpResponse statusCode] >= 400) {
        // do error handling here
           UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Failed" message:@"Check your networking configuration." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
           [alertView show];
    } else {
        // start recieving data
    }
}

This function will be invoked when we have response. After we get response we will start fetching data. There is a separate delegate function for it.

-   (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData{
    NSString *response = [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];

Above function will be invoked when we will have real data. Here response will give us data in string format.

Hope this helps.