Thursday, February 28, 2013

iOS Phonegap ( Cordova ) Open Link in Safari


Have you ever encountered the situation in your corodova project where you have set OpenAllWhitelistURLsInWebView to YES in your Cordova.plist file and you have to open one single URL in external Safari application.? If yes than read this blog.


For cordova we have to whitelist some external urls if we have any. By default it will open in external Safari browser to prevent that we have to set following in Cordova.plist file.

This will open all the external urls in same web view. So to add exception URL which should open in external Safari browser make following changes to AppDelegate.m file. 

- (BOOL) webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL *url = [request URL];
    NSString* urlString =  [url absoluteString];
    
    if ([urlString rangeOfString:@"www.myexternalurl.com"].location == NSNotFound) {

    }
    else {
        [[UIApplication sharedApplication] openURL:[request URL]];
        return NO;
    }
}


and in your JavaScript simply write following line.

window.location.href = "www.myexternalurl.com";

Once web view start loading the url it will invoke shouldStartLoadWithRequest event. Here we are checking the url string and if we find it to be external URL, it will be opened in external Safari browser. Webview will not load this URL since we return NO.

Android Add In-app billing to existing project

Hello,

If you have ever encountered situation, where you need to add In-app billing to your existing project, than this blog is for you. Please note that for this you need Google Play Account and valid Google Merchant Account.

First open Android SDK manager. You can open it from Window - > Android SDK Manager. If it's not available in menu go to Window -> Customize Perspective and Go to third tab  Command Groups Availability.


And check the Android SDK and AVD Manager. Now it should be available in menu. Open it and Go to Extra.


Check the Google Play Billing Library and Click on Install items. This will download necessary files of billing library. Also it will download the sample application. No go to your project src folder in eclipse and Right click on it. Choose Menu New - > Package. Give the name com.android.billing.vending to the package and add file IInAppBillingService.aidl to it. You can find your file in your Android SDK folder at this path extras - > google - > play_billing - > in-app-billing-v03

Now create one more package in in your src and give name com.yourappname. util and add following files to it form sample application. Replace yourappname with your application name.



Now compile your project and it should generate IInAppBillingService.java file in gen folder.


Now add following line to your AndroidManifest.xml file


That's it and now your application is ready for in app billing. For testing use reserved SKUs by google play store. Now create a new activity class and give the suitable name to it. in my case I name it as PurchaseActivity

Add a member to a class 

IabHelper mHelper;

Add following code to onCreate function of activity.

super.onCreate(savedInstanceState);
setContentView(R.layout.activity_purcahse);
String base64EncodedPublicKey = "yourapppublickey";
mHelper = new IabHelper(this, base64EncodedPublicKey);
mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
  public void onIabSetupFinished(IabResult result) {
      if (!result.isSuccess()) {
        // Oh noes, there was a problem.
        Log.d("inappp", "Problem setting up In-app Billing: " + result);
      }
      String purchaseToken = "inapp:"+getPackageName()+":android.test.purchased";
     
      startPurchase();
  }
});

Replace yourapppublickey with your application's public key. For this you need create application in google play store and it give you application public key. Here android.test.purchased is the reserved SKU maintained by Google Play Store for the testing purpose. You don't need to spend money to test it.

Add following functions to your class.

public void startPurchase(){
mHelper.launchPurchaseFlow(this, "android.test.purchased", 10001,   
  mPurchaseFinishedListener, "bGoa+V7g/yqDXvKRqq+JTFn4uQZbPiQJo4pf9RzJ");
}

IabHelper.OnIabPurchaseFinishedListener mPurchaseFinishedListener 
  = new IabHelper.OnIabPurchaseFinishedListener() {
  public void onIabPurchaseFinished(IabResult result, Purchase purchase) 
  {
      if (result.isFailure()) {
        Log.d("inapp", "Error purchasing: " + result);
        return;
      }      
      else if (purchase.getSku().equals("test")) {
      Log.d("inapp","Purchase successful" + result);
      }
  }
};

Once purchased you have to consume purchase. Please note that this blog does not mention the consumption process. This just shows how to test in app billing in your project. Later you can replace the test SKUs with your own SKUs.







Sunday, February 10, 2013

ExtJs Window Resize on Browser Resize

In this blog, I will explain how to resize all the modal window on ExtJs on browser resize. In one of my recent project, I had a requirement to resize all the modal windows open at the same time on browser resize.  Following is the solution.

You must have some main view of app which should be rendered first when app starts. You have to add render event of that view as follow.


this.control({
'mainView': {
render: this.onMainViewRender
        }
});

Now add the following function in your controller file.


onMainViewRender: function() {
Ext.EventManager.onWindowResize( this.onBrowserResize, this );
}

Above function binds the browser resize event and add a callback function to it. Following is the function definition of onBrowserResize

onBrowserResize: function( width, height ) {

Ext.WindowManager.each( function( window ) {

if( !window.isXType( 'window' ) )
                return;                      
if( height < 600 ) {
                                window.maxHeight = height - 30;
                                window.doLayout();
                                window.center();
                        } else {
                                window.maxHeight = 600;
                                window.doLayout();
                                window.center();
                        }
                });
}

It might be possible that we have some message box open at that time so we have to ignore it. That'w why we are checking the window xtype. Here we are setting maxHeight of window. 600 is just the example here. You can change it with your own preference. Else loop is to restore window to it's original height and width if browser is resized to bigger height and width than window.

Hope this helps you.



Sencha Touch, Phonegap (Cordova) application not working in Android 4.x - Here is the Solution

Have you ever encountered this issue? When you try to deploy your Cordova+ Sencha Touch app in Android 4.1, your app is not working. It just shows the white screen. In this blog I will explain the issue and mention solution for it.

What is the Issue?

It's not issue of sencha touch but it's an issue of Android. It's not possible to load any URL in android webview which have certain parameters. This issue is reported since Android 3.0 but still it's not resolved. We know that when we use cordova it uses file protocol to open any files. We load index.html file using following URL.

file:///android_assets/www/index.html 
Now we know that Sencha Touch uses Ext.Loader to load the controllers, stores and model files. When Loader tries to load files, URL would be formed as follow.

file:///android_assets/www/app/controller/MyController.js?_dc=xxxxxxxx

That's why it's break because it adds _dc param in each load request of file. What is this _dc param? This is cache buster param that is added by default by Ext framework. Most of the browsers caches the request and particularly GET request. So Ext framework always add _dc param which has unique datetime stamp. So URL looks always different hence browser does not return cached result. And that's what breaks the app in Android.

What is the Solution?

One solution is to minify all your secha touch classes with Sencha Touch build commands. You have to install Sencha SDK tools and setup necessary environment variables for it. After that go to directory of your application.

cd ~/path/to/my/app

After this create jsb3 file for your application using following command

sencha create jsb -a index.html -p app.jsb3

After this build your application.

sencha build -p app.jsb3 -d ./

This final command takes all of the files listed in the jsb and combines them into a single file, which it then minifies to make as small as possible. The output is a file called all-classes.js, which contains all of the framework classes plus your application classes.

You can reference this file to index.html file so you have minified version of your application and it's ready for the production.


Other solution is to disable caching but that is not recommended. You can disable caching for Ext.Loader as follow.

Ext.Loader.setConfig({ disableCaching: false });

Also you can disable caching for all the Ajax request.

Ext.Ajax.setDisableCaching(false);

This will remove _dc param from your ajax request also Ext.Loader will not add _dc param in file download request.

Hope this helps you.