Guide To Display Images In Grid View On IPhone

In some iOS apps, displaying images in a single view would make the UI lose its uniformity. It would be difficult to manage images of different resolution and impossible to keep track of thousand of images without using Grid View in iPhone.

This is just like a “Grid View” application. Here we will explore how to display images, programmatically in “Grid view” on an iPhone.

Here We Go…

Step 1:

  • Open Xcode
  • Create a View base applicationGridview-123
  • Give the application name “ImageGrid”.

Step 2:

The directory structure is automatically created by the Xcode which also adds up essential frameworks to it. Now, explore the directory structure to check out the contents of the directory.

Step 3:

Here you need to add one ‘NSObject’ class to the project.

  • Select  project -> New File -> Cocoa Touch -> Objective-C class
  • Give the class name “Images”.

Step 4:

Then add an image to the project and give the image name “icon.png”.

Step 5:

  • Open “ImageGridViewController” file and add ‘UITableViewDelegate’ and ‘UITableViewDataSource’
  • Define ‘UITableView’ and ‘NSMutableArray’ classes as well as the buttonPressed: method
  • Import the ‘Image.h’ class and make the following changes.

[sourcecode]#import <UIKit/UIKit.h>
#import "Image.h"
@interface ImageGridViewController:UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *tableView;
NSMutableArray  *sections;
}
@property (nonatomic, retain) UITableView *tableView;
@property (nonatomic, retain) NSMutableArray *sections;
-(IBAction)buttonPressed:(id)sender;
@end[/sourcecode]

Step 6:

  • Double click the ‘ImageGridViewController.xib’ file and open it in the Interface Builder.
  • First drag the ‘TableView’ from the library and place it in the view window.
  • Select ‘tableview’ from the view window and bring up connection inspector and connect ‘dataSource’ to the ‘File’s Owner’ and delegate to the ‘File’s Owner’ icon.
  • Now save the .xib file and go back to Xcode.

Step 7:

In the ‘ImageGridViewController.m’ file, make the following changes:

[sourcecode]#import "ImageGridViewController.h"
#import "Item.h" @implementation ImageGridViewController
@synthesize tableView,sections;

-(void)loadView{

[super loadView];
sections = [[NSMutableArray alloc] init];

for(int s=0;s<1;s++) { // 4 sections
NSMutableArray *section = [[NSMutableArray alloc] init];

for(int i=0;i<12;i++) {// 12 items in each section
Image *item = [[ Image alloc] init];
item.link=@"New Screen";
item.title=[NSString stringWithFormat:@"Item %d", i];
item.image=@"icon2.png";

[section addObject:item];
}
[sections addObject:section];
}
}

– (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sections count];
}

– (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 1;
}

– (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath {
NSMutableArray *sectionItems = [sections objectAtIndex:indexPath.section];
int numRows = [sectionItems count]/4;
return numRows * 80.0;
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {

NSString *sectionTitle = [NSString stringWithFormat:@"Section  %d", section];
return sectionTitle;
}

– (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

static    NSString *hlCellID = @"hlCellID";

UITableViewCell *hlcell = [tableView dequeueReusableCellWithIdentifier:hlCellID];
if(hlcell == nil) {
hlcell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:hlCellID] autorelease];
hlcell.accessoryType = UITableViewCellAccessoryNone;
hlcell.selectionStyle = UITableViewCellSelectionStyleNone;
}

int section = indexPath.section;
NSMutableArray *sectionItems = [sections objectAtIndex:section];

int n = [sectionItems count];
int i=0,i1=0;

while(i<n){
int yy = 4 +i1*74;
int j=0;
for(j=0; j<4;j++){

if (i>=n) break;
Image *item = [sectionItems objectAtIndex:i];
CGRect rect  = CGRectMake(18+80*j, yy, 40, 40);
UIButton *buttonImage=[[UIButton alloc] initWithFrame:rect];
[buttonImage setFrame:rect];
UIImage *buttonImageNormal=[UIImage imageNamed:item.image];
[buttonImage setBackgroundImage:buttonImageNormal forState:UIControlStateNormal];
[buttonImage setContentMode:UIViewContentModeCenter];
NSString *tagValue = [NSString stringWithFormat:@"%d%d", indexPath.section+1, i];
buttonImage.tag = [tagValue intValue];
//NSLog(@tag….%d", button.tag);
[buttonImage addTarget:self
action:@selector(buttonPressed:)forControlEvents:UIControlEventTouchUpInside];
hlcell.contentView addSubview:buttonImage];
[buttonImage release];

UILabel *label = [[[UILabel alloc]initWithFrame:CGRectMake((80*j)-4,                 yy+44, 80, 12)] autorelease];
label.text = item.title;
label.textColor = [UIColor blackColor];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = UITextAlignmentCenter;
label.font = [UIFont fontWithName:@"ArialMT" size:12];
[hlcell.contentView addSubview:label];
i++;
}
i1 = i1+1;
}
return hlcell;
}
-(IBAction)buttonPressed:(id)sender {
int tagId = [sender tag];
int divNum = 0;
if(tagId<100)
divNum=10;
else
divNum=100;
int section = [sender tag]/divNum;
section -=1;// we had incremented at tag assigning time
int itemId = [sender tag]%divNum;
NSLog(@"…section = %d, item = %d", section, itemId);
NSMutableArray*sectionItems = [sections objectAtIndex:section];
Image    *item    =    [sectionItems objectAtIndex:itemId];
NSLog(@"Image selected…..%@, %@", item.title, item.link);

}

-(void)viewDidLoad{
[super viewDidLoad];
}

-(void)didReceiveMemoryWarning{
[super didReceiveMemoryWarning];
}

-(void)viewDidUnload{
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}

-(void)dealloc{
[super dealloc];
}
@end[/sourcecode]

Step 8:

Open the ‘Image.h’ file and make the following changes:

[sourcecode]#import <Foundation/Foundation.h>
@interface Image:NSObject{
NSString*title;
NSString*link;
NSString*image;
}
@property(nonatomic, copy)NSString*title;
@property(nonatomic, copy)NSString*link;
@property(nonatomic, copy)NSString*image;
@end[/sourcecode]

Step 9:

Make the changes in the ‘Item.m’ file:

[sourcecode]#import "Image.h"
@implementation Item
@synthesize title, link, image;
@end[/sourcecode]

Step 10:

Now save it and compile it in the Simulator.

It would be smart to use Grid View to display a number of images in a single view because it enables to manage multiple images efficiently. Users are also facilitated to keep track of their images. It becomes eye soothing and looks great on the iPhone mobile devices.

Keep visiting regularly to Andolasoft blog to know our upcoming article about the process to show your android Smartphone captured images dynamically in “Grid View” Layout.

3 Easy Steps to optimize Queries in Rails using ‘Bullet’

In the world of web development, performance optimization is a crucial aspect that can make or break the user experience. 

One area that often demands attention is database query optimization. Rails developers, rejoice!

The ‘Bullet’ gem is here to help you fine-tune your database queries and boost your application’s speed and efficiency. In this blog, we’ll delve into the steps to optimize queries in your Rails app using the powerful ‘Bullet’ gem.

First,

let me introduce you to the ‘Bullet’ gem

‘Bullet’ is a ruby gem which facilitates the developers by alerting when an application performs an inefficient database query, such as an N+1 query. It is one of the most efficient tool to optimize a Rails application.

Traditional Method (w/o optimization):

This example illustrates the old-fashioned method of optimizing a query.

For example there are two models, one is Order and other is Product’. And an order has many products. Then the code for order listing page will be

In app/controllers/orders_controller.rb

class OrdersController < ApplicationController
  def index
    @orders = Order.all
  end
end

In app/views/orders/index.html.erb

<h1>Orders</h1>

<% @orders.each do |order| %>
  <div class="order">
    <h2><%=link_to order.title, order_path(order)%></h2>
  </div>
  <%order.products.each do |product|%>
     <ul class=”product”>
        <li><%=link_to product.title, product_path(product)%></li>
     </ul>
  <%end%>
<% end %>

These codes would generate N+1 query issues, because here we have queried just once to get the orders and then separate queries for each order to fetch its products. These sorts of problems can be easily overlooked during development.

‘Bullet’ gem comes in handy for avoiding such problems.

Optimized Method – integrating gem ‘Bullet’:

Let me explain in just 3 easy steps, how the gem ‘Bullet’ can be integrated to optimize the query,

Step#1 – Add the gem to the Gemfile

Example

/Gemfile.rb

  gem 'bullet', '4.6.0', :group => “development”

Run “bundle install” to install the bullet gem in the development group.

Step#2 – Configuration setting in development.rb file

To enable Bullet change its configuration with the after_initialize block in the development.rb file. Set alert as true to get alert popup through the browser.

config.after_initialize do 
    Bullet.enable = true 
    Bullet.alert = true  
    Bullet.bullet_logger = true 
    Bullet.console = true 
    Bullet.rails_logger = true 
  end

Step#3 – Restart the Server

Restart the server as well as reload the page.
After completing the above mentioned steps a JavaScript alert popup would appear with the detected N+1 query. The alert would display the file containing the issue as well as what could be done to overcome the problem.

The previous N+1 query can be fixed by following below mentioned steps:

In Controller,

lass OrdersController < ApplicationController
  def index
    @orders = Order.includes(:products)
  end
end

After changing the statement from ‘Order.all’ to ‘Order.includes’(:products). We can fetch the products through eager loading. Now, if we reload the page we wouldn’t get any alert as we are fetching the efficiently. Here the data is fetched by only two queries, one to get the orders and the other to get the products in those orders.

‘Bullet’ can also tell us when we’re doing eager loading unnecessarily. Let’s say in the order listing page only order will be displayed. So, we removed the code that was displaying the list of products. Now after reloading the page we will get an alert popup displaying that Bullet has detected unused eager loading.

Step 4: Run Your App

With ‘Bullet’ enabled, navigate through your application by using its various features. ‘Bullet’ will keep a close eye on your queries and provide alerts if it detects N+1 query problems or suggests eager loading opportunities.

Step 5: Review Alerts

As you interact with your app, pay attention to any alerts generated by ‘Bullet.’ It will notify you about potential N+1 query issues, which occur when a single query fetches associated records for multiple main records, leading to excessive database hits.

Step 6: Eager Loading Optimization

When ‘Bullet’ suggests eager loading, take action by optimising your queries. Use ActiveRecord includes or eager_load methods to load associated records in advance, reducing the need for multiple queries.

Benefits:

  • No need to search the codes in each file to figure out the inefficient database query.
  • Bullet can notify us, through an alert message, by writing in the console or in the log file.
  • Prevent our application from performing an inefficient database query like an N+1 query.
  • It can also detect unused eager loading.

Conclusion

The ‘Bullet’ gem is a powerful tool that empowers Rails developers to optimize their application’s database queries and improve overall performance. 

By following the step-by-step guide outlined in this blog, you can easily integrate ‘Bullet’ into your development workflow, identify potential N+1 query problems, and capitalize on eager loading opportunities. 

Embrace the ‘Bullet’ gem and take your Rails app’s speed and efficiency to new heights, ensuring a seamless and delightful user experience.

Related Questions

Q1: What is the main purpose of the ‘Bullet’ gem in a Rails application?

Ans:
The ‘Bullet’ gem serves as a performance optimization tool in Rails applications. It monitors queries and helps identify potential N+1 query issues and opportunities for eager loading, ultimately optimizing database queries for improved application performance.

Q2: What steps are involved in installing and configuring the ‘Bullet’ gem for query optimization?

Ans:
To optimize queries using the ‘Bullet’ gem, start by adding it to your Gemfile. After installation, configure the gem in your config/environments/development.rb file by enabling it, enabling alerts, and setting up bullet logging. This allows ‘Bullet’ to monitor and alert you about query-related issues.

Q3: How does the ‘Bullet’ gem help in identifying N+1 query issues?

Ans:
The ‘Bullet’ gem identifies N+1 query problems by analyzing your application’s query patterns. If it detects instances where multiple queries are being executed to retrieve associated records for a main record, it generates alerts. These alerts prompt developers to address the issue and optimize queries through eager loading.

Q4: What is eager loading, and how does the ‘Bullet’ gem assist in optimizing it?

Ans:
Eager loading is a technique to fetch associated records in advance to avoid N+1 query problems. The ‘Bullet’ gem suggests opportunities for eager loading by analyzing query patterns. When an N+1 query issue is detected, ‘Bullet’ recommends using ActiveRecord’s includes or eager_load methods to load associated records efficiently.

Q5: What are the benefits of using the ‘Bullet’ gem for query optimization in Rails applications?

Ans:
Using the ‘Bullet’ gem offers several benefits, including optimized queries that reduce database hits, enhanced application performance, increased developer productivity through quick problem identification, and efficient use of eager loading to minimize query-related issues. Overall, it leads to a smoother user experience and improved application responsiveness.

Beginner’s Guide to Cropping Images in PHP Using ImageMagick

While using images in a web application, developers can’t always include images of a particular measurement. In such cases, resizing the images for the application would be a good option but, not efficient either. For example, resizing a long vertical image into a horizontal dimension would just squeeze the image; thereby, affecting the aesthetics of the website and also reducing the purpose of it. Hence it would be smart to implement a cropping tool like ‘ImageMagick’ in order to fit images of various dimensions into a specified size.

ImageMagick is a collection of robust and convenient tools for manipulating images. It can be used to crop images of numerous formats such as JPEG, PNG, GIF, TIFF, PhotoCD and many more. ImageMagick facilitates creation of dynamic images that are fitting to the specific requirements of web applications.

Difference Between Cropping in GD Library and ImageMagic:

GD is the most commonly used extension for PHP. It is popular because it is easier to install and configure (`yum install php-gd` on Fedora, CentOS etc or `sudo apt-get php5-gd` on ubuntu). However, it has some limitations such as:

  • It is comparatively slower
  • It is more memory intensive
  • For certain aspects it can be more complex to use.

Below I have mentioned a sample code for image cropping using GD:

[sourcecode]&amp;amp;amp;lt;?php
function resize_my_image($file, $w, $h, $crop=FALSE) {
list($width, $height) = getimagesize($file);
$r = $width / $height;
if ($crop) {
if ($width &amp;amp;amp;gt; $height) {
$width = ceil($width-($width*($r-$w/$h)));
} else {
$height = ceil($height-($height*($r-$w/$h)));
}
$newGDwidth = $w;
$newGDheight = $h;
} else {
if ($w/$h &amp;amp;amp;gt; $r) {
$newGDwidth = $h*$r;
$newGDheight = $h;
} else {
$newGDheight = $w/$r;
$newGDwidth = $w;
}
}
$src = imagecreatefromjpeg($file);
$dst = imagecreatetruecolor($newGDwidth, $newGDheight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newGDwidth, $newGDheight, $width, $height);

return $dst;
}

$img = resize_my_image(‘/path/to/some/image.jpg’, 150, 150);
?&amp;amp;amp;gt;[/sourcecode]

You can either output it to the browser or save it to a file using the ‘imagejpeg’ function.

Imagick:

Imagick is a less frequently used PECL extension. ImageMagick is a free tool that is used for creating and manipulating images that supports over 100 different image formats. This can be used on a command line tool for any programming language. The Imagick extension essentially provides an API for all of the functionalities available in the `convert` command line tool.

Some of its advantages are:

  • It is faster
  • It uses less memory
  • Offers more powerful functionality
  • Imagick’ is lot easier to use (once you figure out how), your code may end up smaller and cleaner.

The down side of using this extension is that the documentation is extremely limited and there are almost no examples available on the web. Installation on the other hand can be a painful task as well.

Although it should just be a matter of running the command `pecl install imagick`.

Sample code:

Cropping larger images:

Put a big picture named andolasoft_logo.jpg along side with your php page, run the test and check the directory to see andolasoft_logo_thumb.jpg.

Requirement:

imagemagick with imagick extension

[sourcecode]&amp;amp;amp;lt;?php
$obj = new imagick(‘andolasoft_logo.jpg’);
//resize the above image
$obj-&amp;amp;amp;gt;thumbnailImage(160, 0);
//write the thumb
$obj-&amp;amp;amp;gt;writeImage(‘andolasoft_logo_thumb.jpg’);
?&amp;amp;amp;gt;[/sourcecode]

To Crop Animated Image:

[sourcecode]&amp;amp;amp;lt;?php
$image = new imagick(“andolasoft_animated_logo.gif”);
$image = $image-&amp;amp;amp;gt;coalesceImages(); // the trick! To crop animated image
foreach ($image as $frame) {
$frame-&amp;amp;amp;gt;cropImage($width, $height, $x, $y);
$frame-&amp;amp;amp;gt;setImagePage(0, 0, 0, 0); // Remove gif canvas
}
?&amp;amp;amp;gt;[/sourcecode]

$x → The X coordinate of the cropped region’s top left corner
$y → The Y coordinate of the cropped region’s top left corner

Implementing ‘ImageMagick’ would make the website look clean and flawless. Images on the other hand retain its look and feel, thereby making the application look professional and optimized.

Find anything amiss here, then share it with us.

Steps to execute pagination using “Kaminari” gem in Rails3

Pagination is a technique that divides content into manageable chunks, allowing users to easily browse through a dataset. 

In this blog, we’ll dive into the process of implementing pagination using the “Kaminari” gem in a Rails 3 application. 

Kaminari is a powerful and flexible gem that simplifies the pagination process, enhancing the performance and usability of your web application.

Key Features:

  • Easy to use.
  • Customizable engine-based I18n-aware helper.
  • The pagination helper outputs the HTML5 <nav> tag by default and the helper supports Rails 3 unobtrusive Ajax.

Recommended Reading: AJAX Pagination using jQuery in Rails3

Here are the steps to implement “kaminari gem” in a Rails app.

Step#1

  • Put this code in your Gemfile:

[sourcecode]gem ‘kaminari'[/sourcecode]

  • Run “bundle install”

Step#2

  • Modify the controller as mentioned below

[sourcecode]@blogs = Blog.order("name").page(params[:page])[/sourcecode]

Step#3

  • Now, add the paginate helper method in your listing page which is provided by Kaminari, by passing in the list we’re paginating.

[sourcecode]<%= paginate @blogs%>[/sourcecode]

Step#4

  • When the page reloads, the pagination links will be visible. Kaminari will show 25 items per page by default, but we can easily change that by calling another scope called “per” as mentioned below.

[sourcecode]@blogs = Blog.order("name").page(params[:page]).per(10)[/sourcecode]

  • Now it should display 10 items per page.

Step#5

  • You can configure the below mentioned default values of kaminari by running the command

[sourcecode]rails g kaminari:config[/sourcecode]

It’ll generate a file “kaminari_config.rb” in your config/initializers folder with the following code snippet as commented.

[sourcecode]
default_per_page # 25 by default
max_per_page # nil by default
window # 4 by default
outer_window # 0 by default
left # 0 by default
right # 0 by default
page_method_name # :page by default
param_name # :page by default[/sourcecode]

  • Next, you can change the values according to your requirement.
  • If you change your view page like:

[sourcecode]<%= paginate @blogs, :window => 2 %> [/sourcecode]

  • The output will be:

[sourcecode]« First ‹ Prev 1 2 3 4 5 … Next › Last »[/sourcecode]

  • There are some other custom attributes you can use in view page like:

[sourcecode]
<%= paginate @users, :outer_window => 3 %>
<%= paginate @users, :left => 1, :right => 3 %>
<%= paginate @users, :params => {:controller => ‘foo’, :action => ‘bar’} %>
<%= paginate @users, :remote => true %> [/sourcecode]

Kaminari also includes a handy template generator. You can override them by running following command.

[sourcecode]rails g kaminari:views default[/sourcecode]

It’ll generate a “Kaminari” folder in app/views with dependent files inside it.

I hope you liked it. If you want you can contact our experienced ruby on rails developer for your webs and mobile application.
Please leave your comment about this post on the comment section below.

How to Import CSV Configuration File to Device’s SQLite db

Much like web applications, certain Android apps necessitate configuration adjustments to facilitate app testing and deployment across various environments.

Managing configurations for devices has become a critical task. One efficient way to handle configurations is by uploading them to an SQLite database within the device. This approach offers a structured and easily accessible repository for storing and retrieving configurations.

Incorporating distinct web services APIs, we employ the same Android APK to access data from both developmental and staging servers. Additionally, we exercise control over the integrated camera configuration within the Android APK.

Furthermore, seamless operationality demands the implementation of diverse configuration settings within the APK, dynamically applied without necessitating alterations to the source code during runtime.

  • We used different web services API to access data on server, so we need to use same android APK to access data in dev server as well as stager server.
  • We need to control the camera configuration integrated in android APK
  • Similarly, we need different configuration settings to set dynamically in APK without changing the source code at run-time.

Considering the above scenario, the best thing is to use CSV files, such as the properties files used in Java and .NET platform. In Android, we put CSV file in the device’s phone storage (in this example, the file path is “/storage/sdcard0/Android/data/com.example/”).

We have to write codes to read the CSV file and then spilt the data programmatically using separator. Then it has to be inserted in to a SQLite table (in this example uses ‘appconfigtbl‘).

The sample program in this blog will perform the below mentioned steps to achieve the above mentioned initialization of configuration value inside android app:

  • Check if the CSV file exists in the device with proper file path location defined in the APK
  • Use the asynchronous task that runs in the background of the app and initialize the CSV content to the targeted table.
  • While the data is imported from the CSV file to database, the user will see the progress bar of data being uploaded. In case of larger data, the progress bar dialog will be shown with the value of %completed.
  • Since the data is stored in a config-table, the app can retrieve the record from this table and use it in appropriate section.

Benefits:

  • The APK will be re-initialized with basic configuration data at any time.
  • No need to re-write the APK and compile it again.
  • Easier to setup and run inside the device. We get the changed configuration data at run time.
  • APK can be set up to a different configuration data base when required and can be deployed with different config data (CSV file) at different location easily.

Example of CSV File contents (appconfig.csv)

[sourcecode]
Config ID,Config Name,Config Value
validate_url,http://50.56.70.140/
webservice_url,http://50.56.70.140:8080/HOSTAPP/resources/inspection
camera_resolution_hight,800
camera_resolution_width,600
camera_flashlight_mode,auto
long_password,abc123
[/sourcecode]

Example of Layout xml

[sourcecode]
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >

<TextView
android:id="@+id/showResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="" />

[/sourcecode]

Example of  Main form Activity class

1. MainActivity.java

[sourcecode]
package com.example.csvdemo;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.Date;

import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;

public class MainActivity extends Activity {

private boolean isCsvFileNeedToInitialize = true;
private static final int DIALOG_DOWNLOAD_PROGRESS = 0;
private DBHelper mDbHelper;
private ProgressDialog mProgressDialog;
private static int totalRowsUpdate = 0;

public static final String external_sd = Environment.getExternalStorageDirectory().getAbsolutePath();
public static final File sdCard = Environment.getExternalStorageDirectory();
public static final String sdcardBaseDir = sdCard.getAbsolutePath();
public static final String externalPath = "/Android/data/com.example/";
public static final String csvFileName = "appconfig.csv";

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mDbHelper = new DBHelper(this);
mDbHelper.open();
totalRowsUpdate = 0;

// create empty directory if not exist
File appDir = new File(sdcardBaseDir + externalPath);
if(!appDir.exists())
appDir.mkdirs();

File externalResourceFile = new File(sdcardBaseDir + externalPath + csvFileName);
isCsvFileNeedToInitialize = externalResourceFile.exists();
TextView lableResult = (TextView) findViewById(R.id.showResult);

if(isCsvFileNeedToInitialize)
{
new InitializeCSVFileAsync().execute("");

lableResult.setText( totalRowsUpdate + " fetched from ‘appconfig.csv’ into database successfully.");

} else {
lableResult.setText("’appconfig.csv’ not found!");
PopIt("Exit Application", "’appconfig.csv’ not found!");
}
}

public static void setTotalRecord(int ctr) {
totalRowsUpdate = ctr;
}

private void PopIt( String title, String message ){
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setTitle(title);
alertbox.setMessage(message);
alertbox.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
});
alertbox.show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

@Override
protected Dialog onCreateDialog(int id) {
Resources res = getResources();
String reader = "";
int ctr = 0;
try {
File f = new File(sdcardBaseDir + externalPath + csvFileName);
BufferedReader in = new BufferedReader(new FileReader(f));
while ((reader = in.readLine()) != null) { ctr++; }
setTotalRecord(ctr);
}catch(Exception e) {    e.getMessage();  }

switch (id) {
case DIALOG_DOWNLOAD_PROGRESS:
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressDrawable(res.getDrawable(R.drawable.initialize_progress_bar_states));
mProgressDialog.setMessage("Initializing…");
mProgressDialog.setMax(ctr);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(false);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}

// Display Initialize progress bar for uploading CSVFiles to database
class InitializeCSVFileAsync extends AsyncTask<String, String, String>
{
@Override
protected void onPreExecute() {
super.onPreExecute();
mDbHelper.deleteCongigTableOldRecord();
if(isCsvFileNeedToInitialize)
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}
@Override
protected String doInBackground(String… aurl) {
try {
float total = 0F;
float fctr = 1F;
String reader = "";
int ctr = 0;
boolean skipheader = true;
File f = new File(sdcardBaseDir + externalPath + csvFileName);
BufferedReader in = new BufferedReader(new FileReader(f));

while ((reader = in.readLine()) != null) {
// skip header column name from csv
if(skipheader) {
skipheader = false;
continue;
}
String[] RowData = reader.split(",");
mDbHelper.insertDB(RowData);
total += fctr;
publishProgress(""+(int)total);
//publishProgress((int)(total*100/lenghtOfFile));
}
in.close();
} catch(Exception e) {
e.getMessage();
}
return null;
}
protected void onProgressUpdate(String… progress) {
//Log.d("ANDRO_ASYNC",progress[0]);
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}
@Override
protected void onPostExecute(String unused) {

File f = new File(sdcardBaseDir + externalPath + csvFileName);
boolean result = f.delete();
if(isCsvFileNeedToInitialize)
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
mDbHelper.close();
//fillAllList();
}
protected void onDestroy() {
if (mDbHelper != null) {
mDbHelper.close();
}
}
}
}
[/sourcecode]

Example of  Helper class for sqlite database interaction:
Example of AbstractDbAdapter java

[sourcecode]
package com.example.csvdemo;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public abstract class AbstractDbAdapter {

protected static final String TAG = "ExampleDbAdapter";
protected DatabaseHelper mDbHelper;
protected SQLiteDatabase mDb;

protected static final String CONFIG_TABLE_CREATE =
"create table appconfigtbl (_id integer primary key," + "config_name text not null," + "config_value text," + " createdAt text, " + " updatedAt text);";

protected static final String DATABASE_NAME = "example";
protected static final int DATABASE_VERSION = 2;

protected final Context mCtx;

protected static class DatabaseHelper extends SQLiteOpenHelper {

DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(CONFIG_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS CONFIG_TABLE_CREATE");
onCreate(db);
}
}

public AbstractDbAdapter(Context ctx) {
this.mCtx = ctx;
}

public AbstractDbAdapter open() throws SQLException {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.getWritableDatabase();
return this;
}

public void close() {
if (mDbHelper != null) {
mDbHelper.close();
}
//mDbHelper.close();
}
}
[/sourcecode]

Example of DBHelper java

[sourcecode]
package com.example.csvdemo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Hashtable;
import java.util.Vector;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;

public class DBHelper extends AbstractDbAdapter{

public static final String KEY_ROWID = "_id";
public static final String KEY_CONFIG_NAME = "config_name";
public static final String KEY_CONFIG_VALUE = "config_value";
public static final String KEY_POSTED_DATE = "createdAt";
public static final String KEY_EDITED_DATE = "updatedAt";
public int maxLevelOnCurrentMenu = 1;

public int getMaxLevelOnCurrentMenu() {
return maxLevelOnCurrentMenu;
}

public void setMaxLevelOnCurrentMenu(int maxLevelOnCurrentMenu) {
this.maxLevelOnCurrentMenu = maxLevelOnCurrentMenu;
}

public static final String DATABASE_TABLE = "appconfigtbl";

public DBHelper(Context ctx) {
super(ctx);
}

public long insertDB(String config_name,String config_value, String createdAt, String updatedAt) {
ContentValues initialValues = new ContentValues();
initialValues.put(KEY_CONFIG_NAME, config_name);
initialValues.put(KEY_CONFIG_VALUE, config_value);
initialValues.put(KEY_POSTED_DATE,createdAt);
initialValues.put(KEY_EDITED_DATE,updatedAt);
return mDb.insert(DATABASE_TABLE, null, initialValues);
}

public long insertDB(String[] RowData)
{
long result = 0;
ContentValues values = new ContentValues();
values.put(KEY_CONFIG_NAME, RowData[0]);
values.put(KEY_CONFIG_VALUE, RowData[1]);
values.put(KEY_POSTED_DATE, "");
values.put(KEY_EDITED_DATE, "");
result = mDb.insert(DATABASE_TABLE, null, values);
return result;
}

public boolean deleteList(long rowId) {

return mDb.delete(DATABASE_TABLE, KEY_ROWID + "=" + rowId, null) > 0;
}

public boolean deleteCongigTableOldRecord() {

return mDb.delete(DATABASE_TABLE,  null, null) > 0;
}

}
[/sourcecode]

Example of initialize_progress_bar_states.xml [Used to show progressbar UI %progress value]

[sourcecode]

<gradient
android:startColor="#98887b"
android:centerColor="#ddd7c9"
android:centerY="0.95"
android:endColor="#0d1522"
android:angle="270"
/>

<corners
android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp" android:topRightRadius="7dp"/>

<gradient
android:startColor="#74c43f"
android:centerColor="#4a9c14"
android:centerY="0.85"
android:endColor="#06101d"
android:angle="270"
/>
<corners
android:bottomRightRadius="7dp" android:bottomLeftRadius="7dp"
android:topLeftRadius="7dp" android:topRightRadius="7dp"/>

[/sourcecode]