Friday, May 31, 2013

Use SQL Adapter in IBM Worklight 5.0.x

I prepare a simple demo app for team to knowledge sharing to achieve a related goal into worklight.
then I think about why not share on blog by following a great dialog stated "Human knowledge belongs to the world" in movie (I don't remember which one :).

In this blog entry I am not going in much about introduction of Worklight and some of its component but expecting a reader to do few reading using a Google or IBM info center. So

IBM Worklight provide multiple adapters to interact with different media and work as mediator between mobile application and enterprise system. please follow the link to read Overview of IBM Worklight  Adapters. This entry is cover the SQL Adapter.


What is SQL Adapter?

The name itself is expressing, it provides access to enterprise databases to execute the parametrized SQL queries and stored procedures that retrieve or update data in the database.
Below image is illustrate high-level process involve.
 
 

Its Time for Action

Before start assuming you have already setup Worklight environment and now follow the steps is to create a SQL Adapter in Worklight.I have running my MySQL database on my local system. Please follow the step 1 to use this script add table into your schema.
Step 1:
CREATE TABLE `product` (
  `productID` int(11) NOT NULL AUTO_INCREMENT,
  `productName` varchar(255) DEFAULT NULL,
  `Qty` int(10) DEFAULT '0',
  `Model` varchar(255) DEFAULT NULL,
  `price` int(10) DEFAULT '0',
  PRIMARY KEY (`productID`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8

now next step is to create Worklight Adapter.

Step 2:

after hit the finish button this will create the adapter with name Product under adapters folder include 2 files Product.xml and Product-impl.js.

  • Product.xml (to define Data Source for DB and declare procedures you target to invoke)
  • Product-impl.js ( to defined queries to invoke against every procedure you defined in Product.xml)

Now open the Product.xml file and do define the Datasource like this.
<connectivity>
<connectionpolicy xsi:type="sql:SQLConnectionPolicy">
   <datasourcedefinition>
     <driverclass>com.mysql.jdbc.Driver</driverclass>
     <url>jdbc:mysql://localhost:3306/demo</url>
     <user>root</user>
     <password>root</password>
   </datasourcedefinition>
</connectionpolicy>
  <loadconstraints maxconcurrentconnectionspernode="5">
</loadconstraints>
</connectivity>
Note: You have to include “mysql-connector-java-5.1.24-bin.jar” library. If you don’t have one, then download here Download.

if you see your Product-impl.js file you find all you procedures in Step 2 image are automatically generate structure for developer to just change the column name and redefined the query as per need like below. for short explanation I am include two procedure code snippet here one is getProducts fetch all the project and another one is to insert.

/* Select Statement */
var selectProductStatement = WL.Server.createSQLStatement("select "+
"productID, productName, Qty, Model, price from product "+
"ORDER BY productName");

function getProducts() {
 return WL.Server.invokeSQLStatement({
  preparedStatement : selectProductStatement,
  parameters : []
 });
}
/* Insert Statement */
var insertProductStatment = WL.Server
  .createSQLStatement("insert into product "+
" (productName, Qty, Model, price) values (?, ?, ?, ?)");

function addProduct(productName, qty, model, price) {
 return WL.Server.invokeSQLStatement({
  preparedStatement : insertProductStatment,
  parameters : [ productName, qty, model, price ]
 });
}
for testing adapter you can right click on adapter folder -> run as -> Deploy as Worklight adapter. once its deployed successfully you .
now to call this procedure in client side adding a example of Add product.

function addProductRec() {
   var validate = true;
   var query = {};
   if ($("#prod_name").val() != "") {
        query.productName = $("#prod_name").val();
   } else {
        validate = false; 
   }

   if ($("#prod_model").val() != "") {
        query.Model = $("#prod_model").val();
   } else {
        validate = false; 
   }
   
   if ($("#prod_qty").val() != "") {
        query.Qty = $("#prod_qty").val();
   } else {
        validate = false;
   }

   if ($("#prod_price").val() != "") {
        query.price = $("#prod_price").val();
   } else {
        validate = false;
   }

   if (validate) {
       var queryData = JSON.parse(JSON.stringify(query));

       WL.Client.invokeProcedure({
                adapter : "Product",
  procedure : "addProduct",
  parameters : [ queryData.productName, queryData.Qty,
                      queryData.Model, queryData.price ]
  }, {
                  onSuccess : function(result) {
                  $.mobile.changePage("#list", {
          transition : "slide",
   reverse : false,
   changeHash : false
           });
                 getProductsRec();
  },
    onFailure : failureCallback
  });
 } else {
            alert("All fields required");
 }
}
now we are done and its time for testing.
Worklight Console : Screen 1
Worklight Console : Application Screen



Please click here to download the source code.

Saturday, April 27, 2013

Integrate ChildBrowser into Worklight App (IOS Version)

Our team recently trying to get Worklight to open an external URL within a hybrid mobile app. Worklight has an OpenURL function that we first implemented, but the problem with this opens an external URL in the same window as the app,and this isn’t what we are looking for because when URL opens in the same window as the app, it’s difficult to exit the external website, and return to the app flow. So we went with the ChildBrowser plugin to implement child browser functionality within our current running Worklight app. 

During googling I found many people struggling with PhoneGap/Cordova to implement ChildBrowser up.So I come with the solution with easy step and I decided to write a post that hopefully shows up in google for people running and looking for solution.

The ChildBrowser plugin I’m using can downloaded from here.

Create a simple Worklight App name it ChildBrowserDemo. please follow the Figure 1.1

Figure 1.1
Define you app name in second screen or same ChildBrowserDemoApp see Figure 1.2

Figure 1.2

Copy the ChildBrowser.js from ChilBrowserPlugin folder and paste it under common/js folder in your project.
now add this code snipped under the project main html file.
a JavaScript code snippet I used to get it to work. I added a listener on button and call to the install method of the ChildBrowser object. Finally I calling a showWebPage function of childbrowser object that handles the URL opening.

 <h1> Child Browser Demo </h1>        
 <button id="open-child-browser">Open google.com</button>  
 <script>  
 document.getElementById("open-child-browser")  
 .addEventListener("click", function() {   
 try{  
  ChildBrowser.install();  
 }catch(e){  
  alert ("CB Error :"+e);  
 }  
 window.plugins.childBrowser.showWebPage('http://www.google.com');
});  
 </script>  
 <!-- application UI goes here -->  
 <script src="js/initOptions.js"></script>  
 <script src="js/ChildBrowser.js"></script>  
 <script src="js/ChildBrowserDemoApp.js"></script>  
 <script src="js/messages.js"></script>  


Figure 1.3
Now add iphone Worklight environment now build & deploy application this is done for studio side.
After Build & Deploy project from studio right-click on iphone icon and run as xcode project. please follow the below Figure 1.4 for the reference.

Figure 1.4
after opening the project in Xcode drag all of the .m, .h, and .bundle file(s) from the ChilBrowserPlugin folder to the Plugins folder of your project. Make sure the copy option is selected. check Figure. 1.5 below.
Figure 1.5

and then drag the following files into Resources folder into your project.
  1. ChildBrowser.bundle
  2. ChildBrowserViewController.xib
In your project, under the Supporting Files folder, open the Cordova.plist file. You’ll see a bunch of key/value pairs and the one you want is under Plugins. You’ll need to add 2 by clicking the add button that shows when you highlight the Plugins section.
Key: ChildBrowser,        Type:String, Value: ChildBrowser.js
Key: ChildBrowserCommand, Type:String, Value:ChildBrowserCommand

Figure 1.6
Now final step to add these .h and .m files again into Compile Sources to make this plugin available for app in xcode. (otherwise it will prompt ChildBrowserCommand plugin not found error. ) Please follow Figure 1.7.

Figure 1.7
Its time for Testing on Emulator.


Friday, March 15, 2013

How to use IntentSerivce with Broadcast Receiver Android (Flickr Feed)


IntentService is similar solution like AysnTask, but it's purpose is meant for background process like downloading, uploading, or other blocking operations that don't need user interaction to transform this idea into the real so I created the example of flickr feeds to do download operation in background with Broadcast Receiver.

This is how my DownloadService class look like.

DownloadService.java

public class DownloadService extends IntentService {

  private String requestType;

  public DownloadService() {
    super("DownloadService");
  // TODO Auto-generated constructor stub
  }
  
  @Override
  protected void onHandleIntent(Intent intent) {
     
    // TODO Auto-generated method stub
    Bundle bundle = intent.getBundleExtra(AppConstants.FLICKR_BUNDLE);
    requestType = bundle.getString(AppConstants.REQUEST_TYPE);
    if(requestType.equals("FlickrFeeds")) {
        String urlpath = bundle.getString("urlpath");
        getFlickrFeed(urlpath);
    }
  } // onHanlderIntent

}

getFlickrFeed method i created to hit the GET request to flickr api to get feeds from flickr and send the response back to my broadcast receiver using sendBroadcast (Intent intent) method to handle and process it further to display in ListView.

private void getFlickrFeed(String url) {

  DefaultHttpClient httpClient = new DefaultHttpClient();
  HttpGet request = new HttpGet(url);
  String responseData = "";
  try {
   HttpResponse response = httpClient.execute(request);
   if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
    InputStream instream = response.getEntity().getContent();
    BufferedReader rd = new BufferedReader(new InputStreamReader(
      instream));
    StringBuilder total = new StringBuilder();
    String line;
    if (rd != null) {
     while ((line = rd.readLine()) != null) {
      total.append(line);
     }
    }
    // instream.close();
    responseData = total.toString();
    rd.close();
   } else {

    Log.w("HTTP1:", response.getStatusLine().getReasonPhrase());
    response.getEntity().getContent().close();
    throw new IOException(response.getStatusLine()
      .getReasonPhrase());
   }
  } catch (Exception e) {
   e.printStackTrace();
  }

  Intent broadcastIntent = new Intent();
  broadcastIntent.setAction(AppBroadCastReceiver.PROCESS_RESPONSE);
  broadcastIntent.addCategory(Intent.CATEGORY_DEFAULT);

  /* parepare bundle for broadcase */
  Bundle finishBundle = new Bundle();
  finishBundle.putString(AppConstants.RESPONSE_TYPE, "FlickrFeeds");
  finishBundle.putString(AppConstants.RESPONSE_DATA, responseData);
  broadcastIntent.putExtra(AppConstants.FLICKR_BUNDLE, finishBundle);
  sendBroadcast(broadcastIntent);
 }

Now our service class looks ready to hit the wall, Ahem!! Flickr :)
Not Finished Yet!! Its time to call this service from our Activity. As we following this example using BroadCastReceiver Class.

A broadcast receiver extends the BroadcastReceiver class and which is registered as a receiver in an Android Application via the AndroidManifest.xml file or dynamically via the Context.registerReceiver() method.

Alternatively to this static registration, you can also register a broadcast receiver dynamically via the Context.registerReceiver() method.

Note: If registering a receiver in your Activity.onResume() implementation, you should unregister it in Activity.onPause(). Otherwise the system will report a leaked broadcast receiver error. For instance if you registered a receive in in onResume() methods of your activity, you should unregister it in the onPause() by using Context.unregisterReceiver() method.

For retrieving flickr feeds I used Adeel Ansari Flickr PhotoStream.

MainActivity.java with nested AppBroadCastReceiver Code Snippet;

public class MainActivity extends FragmentActivity {
   AppBroadCastReceiver receiver;
   private static DataListFragment list;
   private Button loadFlickrBtn;
   // Adeel Ansari Flickr PhotoStream
   public static String flickrPath = "http://api.flickr.com/services/"
    +"feeds/photos_public.gne?id=47906772@N05&lang=en-us&format=json";

   /**
    * onCreate
    * 
    **/
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        System.out.println("MainActivity onCreate called ");
 }
    
    public void onClick(View view) {

       Intent msgIntent = new Intent(this, DownloadService.class);
       Bundle bundle = new Bundle();
       bundle.putString(AppConstants.REQUEST_TYPE, "FlickrFeeds");
       bundle.putString("urlpath", flickrPath);
       msgIntent.putExtra(AppConstants.FLICKR_BUNDLE, bundle);
       startService(msgIntent);
    }

    @Override
    protected void onResume() {
       // TODO Auto-generated method stub
       IntentFilter filter = new IntentFilter(
       AppBroadCastReceiver.PROCESS_RESPONSE);
       filter.addCategory(Intent.CATEGORY_DEFAULT);
       receiver = new AppBroadCastReceiver();
       registerReceiver(receiver, filter);
       System.out.println("MainActivity onResume called ");
       super.onResume();
    }

    @Override
    protected void onPause() {
       // TODO Auto-generated method stub
       super.onPause();
       System.out.println("MainActivity onPause Called");
       unregisterReceiver(receiver);
    }
}

In onClick method Activity send requests through startService(Intent) calls. The service is started and handle Intent in turn using a worker thread, and stops itself when it runs out of work.

Our Broadcast Receiver class with name AppBroadCastReceiver is defined as nested class in MainActivity.
When implementing a broadcast receiver you have to create a subclass of Android’s BroadcastReceiver and have to implement the onReceive() method.

Android calls the onReceive() method on all registered broadcast receivers whenever the event occurs or sendBroadcast() method allows you to send Intents to your registered receivers.

// nested AppBroadCastReceiver class 
public class AppBroadCastReceiver extends BroadcastReceiver {

  public static final String PROCESS_RESPONSE = Intent.ACTION_VIEW;
 
  @Override
  public void onReceive(Context context, Intent intent) {
   String response = null;
   Bundle receiveBundle = intent
       .getBundleExtra(AppConstants.FLICKR_BUNDLE);
   String responseType = receiveBundle
       .getString(AppConstants.RESPONSE_TYPE);
   System.out.println("onReceive " + responseType);
   if (responseType.equals("FlickrFeeds")) {
 /* Receiving Feeds from url */
 response = receiveBundle.getString(AppConstants.RESPONSE_DATA);
 response = fixJsonResult(response);
 ArrayList flickrFeedsList = parepareList(response);
 FragmentManager fm = getSupportFragmentManager();
 
 // Create the list fragment and add it as our sole content.
 list = new DataListFragment(flickrFeedsList);
 fm.beginTransaction().add(R.id.fragment_container, list)
 .commit();
 }
  }

  public String fixJsonResult(String json) {
   json = json.replace("jsonFlickrFeed(", "");
   json = json.replace("})", "}");
   return json;
  } // fixJsonResult

  private ArrayList parepareList(String response) {
  
   ArrayList flickrFeedsList = new ArrayList();

   try {
      if (response != null && response != "") {
        JSONObject jsonObj = new JSONObject(response);
          if (jsonObj.getJSONArray("items") != null) {
     JSONArray jobPosts = jsonObj.getJSONArray("items");
            
            for (int i = 0; i < jobPosts.length(); i++) {
              flickrFeedsList.add(new FlikrFeed(jobPosts
  .getJSONObject(i)));
            }
         }
       }
     } catch (JSONException e) {
        e.printStackTrace();
     }
     return flickrFeedsList;
  } // parepareList

} // AppBroadCastReceiver

In onReceive method this receive a json data fetch by service and displaying feeds in listView, I used DataListFragment class which extends ListFragment and prepare the result to view in the list.

App Screen Shots:


Download Source Code.: https://github.com/m-saifuddin/AndroidProjOne

Reference :
1) Android Service Tutorial by (By Lars Vogel)
2) Android Tutorial: BroadcastReceiver by Wolfram Rittmeyer

Wednesday, December 26, 2012

zBar integeration with IOS iphone/ipad.


Few Days back I started learning IOS, and asked me to integrate Bar Code Scanner within application. After spent few hours I found the zBar SDK for iphone and found this very easy to implement within app.

So this simple scanner barcode view looks like.

















To build this interface I follow this steps.

  1. Create new project in xcode.
  2. Select Single View Application under IOS->Application Tab (Press Next)
  3. I used the app name ZbarExample in product name and select two checkboxes "Use storyboard" and "Use Automatic Reference Counting".
  4. Now click to mainStoryboard.storyboard file. Drag a label onto the view and customize the placement and appearance as you like.
  5. Drag a Round Rect Button onto the view and title it “Scan”. Customize the placement and appearance as you like.
Now we're going to make an outlet for this label field on the ViewController using Assistant Editor feature of Xcode. Open the Assistant Editor with the button from the toolbar (the one that looks like tuxedo/ alien face). it should automatically open on ViewController.h

Select the label field and ctrl-drag into the .h file:
Let go of the mouse button and a popup appears:

Name the new outlet "viewResult". After you click Connect, Xcode will add the following property to ViewController.h:

do the same for button and name it "scan" and select IBAction in connection this time.

and your file should look like this.

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (strong, nonatomic) IBOutlet UILabel *viewResult;

- (IBAction)scan:(id)sender;

@end

Entries of that code inserted in ViewController.m file automatically.

Now its time to integrate Zbar Sdk into our example.

Use this http://zbar.sourceforge.net/iphone/sdkdoc/install.html to download and integrating step to follow.

After download and add following framework in your app.

Open ZBarSDK-1.2.dmg in the Finder.(its appear like something)

















Drag the ZBarSDK folder into your Xcode project. In the dialog that appears, you should choose to copy the SDK into your project by checking the box.


















The target that you want to link with the library should also be selected in the target list.


Link the following additional frameworks to any targets that link with the ZBarSDK. You should set the first three to use weak references and configure an appropriate deployment target if you still need to support iOS 3:
  • AVFoundation.framework (weak)
  • CoreMedia.framework (weak)
  • CoreVideo.framework (weak)
  • QuartzCore.framework
  • libiconv.dylib
If you check “Link Binary With Libraries” for the target(s), you should see all of these frameworks followed by libzbar.a.

Import the SDK header from your prefix header to make the barcode reader APIs available and include ZBarReaderDelegate like this.


#import <UIKit/UIKit.h>
#import "ZBarSDK.h"

@interface ViewController : UIViewController <ZBarReaderDelegate> {
}

@property (strong, nonatomic) IBOutlet UILabel *viewResult;

- (IBAction)scan:(id)sender;

@end

now move to the ViewController.m file and replace this code into scan method and don't forget to import ZBarSDK.h in same.

- (IBAction)scan:(id)sender {
      
    //initialize the reader and provide some config instructions
    ZBarReaderViewController *reader = [ZBarReaderViewController new];
    reader.readerDelegate = self;
    
    [reader.scanner setSymbology: ZBAR_I25
                          config: ZBAR_CFG_ENABLE
                              to: 1];
    reader.readerView.zoom = 1.0; // define camera zoom property
    
    //show the scanning/camera mode
    [self presentModalViewController:reader animated:YES];
    // Do any additional setup after loading the view from its nib.

}


And add this method in same ViewController.m file.

- (void) imagePickerController: (UIImagePickerController*) reader
 didFinishPickingMediaWithInfo: (NSDictionary*) info {
    
    //this contains your result from the scan
    id results = [info objectForKey: ZBarReaderControllerResults];
    
    //create a symbol object to attach the response data to
    ZBarSymbol *symbol = nil;
    
    //add the symbol properties from the result
    //so you can access it
    for(symbol in results){
        
 //symbol.data holds the value        
        NSString *upcString = symbol.data;
        
        //print to the console
        NSLog(@"the value of the scanned UPC is: %@",upcString);
        
        NSMutableString *message = [[NSMutableString alloc] 
        initWithString: @"Scanned Barcode: "];
        
        [message appendString:[NSString stringWithFormat:@"%@ ",
        upcString]];
        
        //Create UIAlertView alert
        UIAlertView  *alert = [[UIAlertView alloc] 
        initWithTitle:@"Product Barcode" message: message delegate:self 
        cancelButtonTitle:@"Cancel" otherButtonTitles: nil];
        
        self.viewResult.text = upcString;
        [alert show];
        //After some time
        [alert dismissWithClickedButtonIndex:0 animated:TRUE];
        
        //make the reader view go away
        [reader dismissModalViewControllerAnimated: YES];
    }
    
}



Time for Testing. :)

Download Source Code.: https://github.com/m-saifuddin/iphone