Building an Android Application in 6 Steps

  • Look up employees by name in a local SQLite database
  • Look at the details of an employee
  • Call, email, text an employee from within the application
  • Navigate up and down the organization’s org chart

You can download the Eclipse projects here. includes a project for each step. EmployeeDirectory6 is the final application. If you prefer, you can also browse the source codehere.

Setting Up and Running the Projects in Eclipse

Here are some quick steps to set up and run the projects in Eclipse. If you just want to see how the application is built without setting up the projects, go straight to Step 1 below.

  1. Download here (or check out the project from the trunk).
  2. Follow the steps described here to install the Android SDK and the ADT plugin for Eclipse.
  3. In Eclipse, create a new Workspace and set its default Java Compiler compliance level to 1.5.
  4. Import the projects: File > Import > General > Existing Projects into Workspace, and point to the androidtutorial directory.
  5. Click here for instructions on how to run your projects using the Android emulator or on your device.

Step 1: Basic Layout

In this first step, we define the user interface for searching employees.

Code highlights: The default Activity of the application. setContentView() is used to set the layout to main.xml.

main.xml: the layout for the default activity of the application.

Step 2: Working with Lists

In this second step, we add a ListView component that will be used (in the following step) to display the list of employees matching the search criteria. In this step, we just use an ArrayAdapter to display sample data in the list.

Code highlights:

main.xml: The updated layout with the ListView. An ArrayAdapter is used to populate the ListView.

Step 3: Working with a SQLite Database

In this third step, we use a SQLite database to persist the employees. When the user clicks the Search button, we query the database, and populate the list with the employees matching the search criteria.

Code highlights:

  • In onCreate(), we use the DatabaseHelper class to open the database.
  • In search(), we use a Cursor to query the database. We then use a SimpleCursorAdapter to bind the ListView to the Cursor using a custom layout (employee_list_item) to display each item in the list. We extend SQLiteOpenHelper to manage the access to our database: If the database doesn’t yet exist, we create the employee table and populate it with sample data.

employee_list_item.xml: Layout to display each item in the list.

Step 4: Using Intents and passing information between Activities

In this fourth step, we create an Activity to display the details of the employee selected in the list. We start the EmployeeDetails activity by creating an Intent.

Code highlights: in onListItemClick, we create a new Intent for the EmployeeDetails class, add the employee id to the intent using intent.putExtra(), and start a new Activity. The Employee details activity. We retrieve the id of the employee using getIntent().getIntExtra(). We then use a Cursor to retrieve the employee details.

employee_details.xml: A simple layout to display the details of an employee.

Step 5: Calling, Emailing, and Texting an Employee

In this fifth step, we interact with some of the built-in capabilities of our phone. We use Intents to allow the user to call, email, or text an employee. We reuse the EmployeeDetails Activity to allow the user to display the details of the manager of the selected employee.

Code highlights:

  • In onCreate(), we build an array of actions (call, email, sms, view manager) available to the user depending on the information available for the displayed employee (for example, we only create a “Call mobile” action if the employee’s mobile phone number is available in the database).
  • EmployeeActionAdapter is a custom list adapter that binds each action in the actions array to the action_list_item layout.
  • In onListItemClick(), we create an Intent corresponding to the action selected by the user, and start a new activity with that intent.

action_list_item.xml: Layout for each action in the actions list.

employee_details.xml: Updated employee details layout.

Step 6: Navigating Up and Down the Org Chart

In this sixth step, we create a new Activity to display the Direct Reports of the selected employee, allowing the user of the application to navigate up and down the org chart of the organization. We also improve some elements of the application: for example, we polish the user interface in several layouts, and we populate the database using an XML documents as opposed to the hardcoded sample data used in the previous steps.

Code highlights: A new Activity to display the direct reports of a specific employee.

direct_reports.xml: The layout for the DirectReports Activity. “View direct reports” is added to the list of actions. When the user selects that action, a new Intent is created for the DirectReports Activity, and a new Activity is started using that Intent. Instead of populating the database with hardcoded sample data, the employee table is now created and populated from an XML file (sql.xml).

sql.xml: The xml file used to create and populate the employee table.

By beatsoftech

How To Create A Simple iPhone App on iOS

The iPhone is an amazing platform to develop on for indie software developers. It’s never been easier to come up with your own unique app idea, code something up, and have it be available to millions of potential customers!

Lately I’ve been getting a lot of questions from people new to iOS development asking how to get started. So I thought it would be helpful to write a tutorial series tailored for beginners.

But rather than focusing in detail on just one topic, we’re going to dive in and create an entire functional app from scratch. By the end, you’ll have tried out many areas of iPhone development, and ready to dig in further.

So what’s the app we’re going to make? Well, there’s a story behind that…

The other night, I saw a picture of a Potato Bug for the first time and started freaking out because it was so big and ugly! Then I got obsessed with looking up all kinds of scary bug pictures online. So to spread the fun, we’re going to make an app for that – rating scary bugs!

While making this app, we’ll cover some of the most commonly used topics in iPhone development:

  • What You Need to Get Started with iPhone Development
  • How to store your app data in a Model
  • How to use Table Views – including adding and deleting rows
  • How to create a detail view for a row
  • How to support both Portrait & Landscape orientations
  • How to use Navigation Controllers
  • How to use an Image Picker
  • How to use common controls such as a text field, button, and image view
  • How to add icons and default images
  • Bonus: How to handle long-running operations

It sounds like a lot, but don’t get scared – we’re not afraid of no bugs!

In this first part of this three-part series, we’ll cover how to load our model with a list of bugs and display them in a table view. (Jump to Part 2 or Part Three)

This tutorial is for beginner iOS developers, however it assumes you are familiar with Objective-C and programming in general. If you are new to Objective-C, I recommend reading Apple’s Objective-C Programming Language Guide first.

What You Need

First things first – to develop for the iPhone, you’ll need a Mac. Pretty much any Mac will do, as long as it’s powerful enough to run the latest version of the Mac OS, Lion. But if you’re looking to go the cheap route, you can pick up a Mac Mini for relatively cheap, and it works just fine for a development machine.

Next, you’ll need to get a copy of XCode, Apple’s IDE for iOS development. So if you haven’t already, register for a free account at the iPhone Dev Center and download a copy of Xcode from the Mac App Store.

If you’d like, you can sign up for the paid iPhone Developer Program that allows you to distribute your apps on the App Store, but if you just want to try out iOS development the free account works fine.

If you get serious about iOS development, you’ll probably want physical device(s) (iPhone/iPhone 4/iPod Touch/iPad) as well. It’s true that you can do a lot of testing with just the Simulator, but there are some APIs that don’t work on the Simulator, and you’ll need a physical device for performance testing.

That’s it – so if you haven’t already, grab a copy of XCode, fire it up, and let’s continue on!

Hello, Table View!

We’re going to start out by using one of the most common controls on the iPhone – the Table View. You’ve probably seen the Table View in a lot of apps already, here are a few examples:

UITableView Examples

So anyway, our first screen in the app will have one of these, to display a list of scary bugs!

Let’s get started by going to File\New Project in XCode, select the iOS\Application\Master-Detail Application, and click Next.

Creating an app with the master detail application template

On the next page, enter ScaryBugs for the Product Name, enter a unique string for your company identifier (com.yourcompanyname or com.yourname is best), select iPhone for the device family, and make sure Use Storyboard and Use Automatic Reference Counting is selected. Click Next when you’re done.

Project Settings for scary bugs app

Choose a place to save your project and click Create. And before we do anything else, let’s check out what we’ve got so far! In the toolbar at the top of the screen pick iPhone Simulator from the list, then click the Run button. If all goes well, you should see the following in your simulator:

The main screen created by the master detail template

You can tap on the detail entry in the table view, and it will take you to a blank page like this:

Detail view created by master detail application template

So as you can see, we already have a working project to start from since we chose the Master-Detail Application template.

We’re not going to dig into the template since that’s beyond the scope of this tutorial, but just notice that we have an empty table view and detail view set up for us and ready to go – we just have to fill it in with data!

So to do that, let’s create a class to keep track of our scary bugs.

A Scary Data Model: Organization

Notice how there’s a hierarchy of folders in the Project Navigator section of XCode:

The project navigator in Xcode

The template comes set up with a root group, and a Supporting Files group. These groups are just for organizational purposes, so feel free to change them however you want. In our case, we’re going to have a fair number of files in this project, so let’s organize things a bit.

First, create a new group to store the User Interface files in. To do this, control-click the Scary Bugs group and select New Group. Then control click the new group it created and select rename, and name it “GUI”. Drag the existing files from the root into the GUI group (but not Supporting Files). It should now look like this:

Organizing Project Navigator tree, part 1

Now create a second new group, and name it “Model”, because we’re about to add couple classes for our data model there. Your tree should now look like the following:

Creating a group for the model

Before we begin, let’s talk about how we’re going to organize things:

  1. ScaryBugData: Contains bug name and rating.
  2. ScaryBugDoc: Contains full size image, thumbnail image, ScaryBugData.

The reason we’re setting things up like that is it will make things easier in the follow-up for this tutorial, where we’re going to start saving our data to the disk, implementing file sharing, and the like.

A Scary Data Model: Implementation

Ok so let’s do it! Control-click on the Model group and click “New File…”. Select the iOS\Cocoa Touch\Objective-C class template, and click Next.

Creating a file with the Objective-C class template

Name the class ScaryBugData, enter NSObject for subclass, and click Next.

Creating a class that derives from NSObject in Xcode

In the final popup, click Create again. If all went well, your Project Navigator should now look similar to this:

Project organization, part 3

Ok, time to create our ScaryBugData class. Replare ScaryBugData.h with the following:

#import <Foundation/Foundation.h>
@interface ScaryBugData : NSObject
@property (strong) NSString *title;
@property (assign) float rating;
- (id)initWithTitle:(NSString*)title rating:(float)rating;

This is pretty simple stuff – we’re just declaring an object with two properties – a string for the name of the bug, and a float for how scary we rated it. We use two property attributes for these:

  • strong: This specifies that the runtime should automatically keep a strong reference to the object. This is a fancy way of saying that the ARC runtime will keep the object in memory as long as there’s a reference to it around, and deallocate it when no references remain. For more information, check out our Beginning ARC in iOS 5 Tutorial.
  • assign: This means the property is set directly, with no memory management involved. This is what you usually set for primitive (non-object) types like a float.

We also define an initializer for the class, so we can set the title and rating when we create the bug.

Switch over to ScaryBugData.m and replace it with the following:

#import "ScaryBugData.h"
@implementation ScaryBugData
@synthesize title = _title;
@synthesize rating = _rating;
- (id)initWithTitle:(NSString*)title rating:(float)rating {
    if ((self = [super init])) {
        self.title = title;
        self.rating = rating;
    return self;

Again, extremely simple stuff here. We synthesize our properties, and create our initializer to fill in our instance variables from the passed-in parameters. Note there is no need for dealloc, since we are using ARC.

Ok that’s it for ScaryBugData. Now follow the same steps you did above to create another subclass of NSObject, this time named ScaryBugDoc.

Replace ScaryBugDoc.h with the following:

#import <Foundation/Foundation.h>
@class ScaryBugData;
@interface ScaryBugDoc : NSObject
@property (strong) ScaryBugData *data;
@property (strong) UIImage *thumbImage;
@property (strong) UIImage *fullImage;
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage;

Nothing of particular note here – just creating some instance variables/properties and an initializer.

Replace ScaryBugDoc.m with the following:

#import "ScaryBugDoc.h"
#import "ScaryBugData.h"
@implementation ScaryBugDoc
@synthesize data = _data;
@synthesize thumbImage = _thumbImage;
@synthesize fullImage = _fullImage;
- (id)initWithTitle:(NSString*)title rating:(float)rating thumbImage:(UIImage *)thumbImage fullImage:(UIImage *)fullImage {   
    if ((self = [super init])) { = [[ScaryBugData alloc] initWithTitle:title rating:rating];
        self.thumbImage = thumbImage;
        self.fullImage = fullImage;
    return self;

And that’s it – our data model is complete! Time to create some sample data and display it in the table view.

A Different Kind of Bug List

First, let’s set up our table view so it can handle displaying a list of ScaryBugDocs. The first thing we have to do is modify our table view so that it returns a dynamic list of rows (rather than a hardcoded single row that the template set up for us).

To do this, open MainStoryboard.storyboard. This allows you to visually layout the different “screens” in your app. As you can see, the app is currently set up to have a navigation controller (the thing that makes it easy to slide between different screens), with the root controller the “master” screen, and a secondary controller as the “detail” screen.

Main Storyboard layout

Select the Master View Controller, and in the selection area in the left panel, select the table view. In the inspector to the right, set the Content to Dynamic Prototypes.

Setting table view to use dynamic prototype cells

This allows you to layout a table view cell the way you like in the Storyboard Editor, and fill them in via code. We just want a basic cell, so let’s set the cell to use the Basic style.

Select the table view cell on the left, and in the Attributes Inspector set the Style to Basic. Also set the Identifier to MyBasicCell.

Setting cell style and reuse identifier

For more information on creating custom cells, check out our Beginning Storyboards in iOS 5 Tutorial.

OK, now that we have our table view set up correctly visually, we just need to update the code to fill in the table with a list of scary bugs.

We’ll store our ScaryBugDocs in a NSMutableArray, the collection class that you use for arrays that should be able to dynamically change in size.

Add the following line to MasterViewController.h, between the @interface and @end lines:

@property (strong) NSMutableArray *bugs;

This will be the instance/variable property that we’ll use to keep track of our list of bugs.

Now go over to MasterViewController.m and make the following changes:

// At top of file
#import "ScaryBugDoc.h"
#import "ScaryBugData.h"
// After @implementation
@synthesize bugs = _bugs;
// At the end of viewDidLoad
self.title = @"Scary Bugs";
// Replace the return statement in shouldAutorotateToInterfaceOrientation with:
return YES;
// Replace the return statement in tableView:numberOfRowsInSection with the following:
return _bugs.count;
// Add the following new methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    return 1;
- (NSInteger)tableView:(UITableView *)tableView
    return [self.bugs count];
- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
    UITableViewCell *cell = [tableView
    ScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
    cell.textLabel.text =;
    cell.imageView.image = bug.thumbImage;
    return cell;

Ok, finally something interesting to discuss!

First, note that we set a property on ourselves called “title” to the string “Scary Bugs.” “title” is a special built-in property on view controllers. When a Navigation Controller displays a view controller, it shows whatever is in the “title” property in the title bar. So by setting this, we should see “Scary Bugs” up top!

Next, note we return yes in shouldAutorotateToInterfaceOrientation, which tells the OS that we should be able to support all orientations – Portrait, Landscape, and the updside down versions of each. Since this class is a UITableViewController, that’s all we have to do – the view will rotate automatically from there!

Next, when constructing a table view with dynamic rows have to override numberOfSectionsInTableView and numberOfRowsInSection to tell the OS how many sections/rows should be displayed in the table view. We just have 1 section, so we don’t have to do anything because the template is already set up to return 1 section. For the rows, we just return the number of objects in our bugs array.

Finally, we implement tableView:cellForRowAtIndexPath, which is probably the most important method to implement when making a table view. Here, you set up the cell that will be displayed for a particular row. The OS will call this method once per row for each row so you can set it up.

Let’s take a look this method in detail, since this is particularly important:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
    UITableViewCell *cell = [tableView
    ScaryBugDoc *bug = [self.bugs objectAtIndex:indexPath.row];
    cell.textLabel.text =;
    cell.imageView.image = bug.thumbImage;
    return cell;

The first line calls a helper function called “dequeueReusableCellWithIdentifier” to try to return a reusable cell. What is this all about?

Well, it’s an important performance optimization. Keep in mind that table views can contain a very large number of rows, but only a certain number of them are displayed on screen at a time. So rather than creating a new cell each time a new row cycles into the screen, the OS can improve performance by re-using a cell that was already created, but scrolled off-screen.

So that’s what the dequeueReusableCellWithIdentifier call is. If there’s not a reusable cell available, we just create a new cell based on the cell you set up in Interface Builder (remember how we set it as basic, and named it “MyBasicCell”?).

You can create your own table view cells, or use a standard one. In our case, the default table view works fine, so we just pick that by setting the style to UITableViewCellStyleDefault.

If you’re curious what the different standard table view cell options look like, check out the “Standard Styles for Table-View Cells” section in the Table View Programming Guide.

Finally, we configure the cell by setting its textLabel and imageView (which are available with the Basic style).

Believe it or not that’s all we need to do! Now we just need to set up some sample data for the table view to display.

Scary Bug Pictures!

But of course we’ll need some scary bug pictures for that! You can either browse the Internet and find some, or download these Scary Bug Pictures I found on stock.xchng.

Once you’ve downloaded the files or gotten your own, drag them all into the root of your Project Navigator tree. When the popup appears, make sure “Copy items into destination group’s folder (if needed)” is checked, and click Add.

Adding scary bugs files to project

Then open up ScaryBugsAppDelegate.m and make the following changes:

// At top of file
#import "MasterViewController.h"
#import "ScaryBugDoc.h"
// At beginning of application:didFinishLaunchingWithOptions
ScaryBugDoc *bug1 = [[ScaryBugDoc alloc] initWithTitle:@"Potato Bug" rating:4 thumbImage:[UIImage imageNamed:@"potatoBugThumb.jpg"] fullImage:[UIImage imageNamed:@"potatoBug.jpg"]];
ScaryBugDoc *bug2 = [[ScaryBugDoc alloc] initWithTitle:@"House Centipede" rating:3 thumbImage:[UIImage imageNamed:@"centipedeThumb.jpg"] fullImage:[UIImage imageNamed:@"centipede.jpg"]];
ScaryBugDoc *bug3 = [[ScaryBugDoc alloc] initWithTitle:@"Wolf Spider" rating:5 thumbImage:[UIImage imageNamed:@"wolfSpiderThumb.jpg"] fullImage:[UIImage imageNamed:@"wolfSpider.jpg"]];
ScaryBugDoc *bug4 = [[ScaryBugDoc alloc] initWithTitle:@"Lady Bug" rating:1 thumbImage:[UIImage imageNamed:@"ladybugThumb.jpg"] fullImage:[UIImage imageNamed:@"ladybug.jpg"]];
NSMutableArray *bugs = [NSMutableArray arrayWithObjects:bug1, bug2, bug3, bug4, nil];
UINavigationController * navController = (UINavigationController *) self.window.rootViewController;
MasterViewController * masterController = [navController.viewControllers objectAtIndex:0];
masterController.bugs = bugs;

Here we just use the ScaryBugDoc initializer to create four sample bugs, passing in the title, rating, and images for each. We add them all to a NSMutableArray, and set them on our table view.

Speaking of which, we can get a pointer to the RootViewController since we know it’s the first view controller in the navigation controller’s stack. There are other ways we could have gotten a pointer as well, but this is one easy way.

And that’s it! Compile and run your app, and if all works well, you should see a list of (mostly) frightening bugs in your table view!

Scary Bugs Table View

By beatsoftech

ആന്‍ഡ്രോയിഡ് ഫോണുണ്ടോ, എങ്കില്‍ സി.പി.യു. വേണ്ട

ഡ്യുവല്‍ കോര്‍ പ്രൊസര്‍, ഒരു ജിബി റാം, 512 എംബി റോം… കമ്പ്യൂട്ടറുകളുടെ സ്‌പെസിഫിക്കേഷനെക്കുറിച്ചാണ് പറയുന്നതെന്ന് കരുതുന്നുവര്‍ക്ക് തെറ്റി. നമ്മുടെ പോക്കറ്റുകളില്‍ കൊള്ളുന്ന സ്മാര്‍ട്‌ഫോണിന്റെ ഉള്ളിലുള്ള കാര്യങ്ങളാണിത്. ഹാര്‍ഡ്‌വേര്‍ സൗകര്യങ്ങളുടെ കാര്യത്തില്‍ പരസ്പരം കടുത്ത മത്സരത്തില്‍ ഏര്‍പ്പെട്ടിരിക്കുകയാണ് സ്മാര്‍ട്‌ഫോണ്‍ ബ്രാന്‍ഡുകള്‍. ലാപ്‌ടോപ്പുകളോടും പേഴ്‌സണല്‍ കമ്പ്യൂട്ടറുകളോടുമാണ് പുതുഫോണുകള്‍ ശക്തി പരീക്ഷിക്കുന്നത്. ഒരു ലാപ്‌ടോപ്പിനേക്കാള്‍ ഹാര്‍ഡ്‌വേര്‍ കരുത്തും സോഫ്ട്‌വേര്‍, മള്‍ട്ടിമീഡിയ സൗകര്യങ്ങളുമുള്ളതാണ് ഇന്നിറിങ്ങുന്ന മിക്ക സ്മാര്‍ട്‌ഫോണുകളും. പിന്നെയെന്തിനാണ് ആളുകള്‍ സ്മാര്‍ട്‌ഫോണും ലാപ്‌ടോപ്പും ഒരുമിച്ചുകൊണ്ടുനടക്കുന്നത്, ഏതെങ്കിലും ഒന്നുപോരേ കൈയില്‍?

ഈ ചോദ്യത്തിന് ഉത്തരം നല്‍കുകയാണ് പ്രമുഖ സോഫ്ട്‌വേര്‍ കമ്പനിയായ കാനോണിക്കല്‍ ലിമിറ്റഡ്. ലിനക്‌സ് സംവിധാനത്തില്‍ പ്രവര്‍ത്തിക്കുന്ന ഉബുണ്ടു ഓപ്പറേറ്റിങ് സിസ്റ്റത്തിന്റെ നിര്‍മാതാക്കളാണ് കാനോണിക്കല്‍. കമ്പനി ഏറ്റവുമൊടുവില്‍ പുറത്തിറക്കിയിട്ടുള്ള ‘ഉബുണ്ടു ഫോര്‍ ആന്‍ഡ്രോയിഡ്’ സോഫ്ട്‌വേര്‍, ആന്‍ഡ്രോയിഡ് ഒഎസുള്ള ഫോണുകളെ കമ്പ്യൂട്ടര്‍ പോലെ പ്രവര്‍ത്തിപ്പിക്കാന്‍ സഹായിക്കുന്നു. ബാഴ്‌സലോണയില്‍ മൊബൈല്‍ വേള്‍ഡ് കോണ്‍ഗ്രസിലാണ് ഈ സോഫ്ട്‌വേര്‍ ഔദ്യോഗികമായി അവതരിപ്പിക്കപ്പെട്ടത്്.

കമ്പ്യൂട്ടര്‍ മോണിട്ടറുമായി ഈ സോഫ്ട്‌വേറുള്ള സ്മാര്‍ട്‌ഫോണ്‍ കണക്ടുചെയ്താല്‍ ഉബുണ്ടു ഒഎസില്‍ പ്രവര്‍ത്തിക്കുന്ന ഡെ്‌സ്‌ക്‌ടോപ്പ് സ്‌ക്രീനില്‍ തെളിഞ്ഞുവരും. ഒരു കീബോര്‍ഡും മൗസും കൂടിയുണ്ടെങ്കില്‍ ശരിക്കും കമ്പ്യൂട്ടര്‍ പോലെ ഈ സംവിധാനം പ്രവര്‍ത്തിക്കും. സിപിയുവിന്റെ ധര്‍മം സ്മാര്‍ട്‌ഫോണ്‍ ഏറ്റെടുത്തുകൊള്ളുമെന്നര്‍ഥം. 

ഫോണിലുള്ള മുഴുവന്‍ ഡാറ്റയും ഡെസ്‌ക്‌ടോപ്പിലൂടെ ആക്‌സസ് ചെയ്യാനാകും. ഫോണിലെ വീഡിയോകള്‍ കമ്പ്യൂട്ടറില്‍ കാണാം. ഫോണിലുള്ള നമ്പറുകളിലേക്ക് സ്‌കൈപ്പ് പോലുള്ള സംവിധാനങ്ങളുപയോഗിച്ച് ഡെസ്‌ക്‌ടോപ്പിലൂടെ സംസാരിക്കാനുമാകും. ഇന്റര്‍നെറ്റ് ബ്രൗസിങിനായി ഫയര്‍ഫോക്‌സ്, ക്രോം എന്നീ ബ്രൗസറുകളും ഇതിലുണ്ട്. ഡെസ്‌ക്‌ടോപ്പിലേക്ക് കണക്ട് ചെയ്യുമ്പോള്‍ ഫോണില്‍ സെറ്റ് ചെയ്തുവെച്ചിരിക്കുന്ന അതേ ബുക്ക്മാര്‍ക്കുകളും വെബ്ഹിസ്റ്ററിയും ലഭിക്കുമെന്നതും ഇതിന്റെ സൗകര്യമാണ്.

കമ്പ്യൂട്ടര്‍, സ്മാര്‍ട്‌ഫോണ്‍ മേഖലകളില്‍ വിപ്‌ളവകരമായ മാറ്റങ്ങള്‍ക്ക് വഴിയൊരുക്കാന്‍ ‘ഉബുണ്ടു ഫോര്‍ ആന്‍ഡ്രോയിഡ്’ സോഫ്ട്‌വേറി’ന് സാധിക്കുമെന്ന് കാനോണിക്കല്‍ സ്ഥാപകന്‍ മാര്‍ക്ക് ഷട്ടില്‍വര്‍ത്ത് അവകാശപ്പെടുന്നു. ഓരോ ജീവനക്കാര്‍ക്കും പ്രത്യേകം ലാപ്‌ടോപ്പുകള്‍ കൊടുക്കുന്നതിനുപകരം കമ്പനികള്‍ക്ക് ഇനിയൊരു ആന്‍ഡ്രോയിഡ് ഫോണ്‍ മാത്രം നല്‍കിയാല്‍ മതിയാകും. സിപിയുവിന്റെയും പ്രത്യേകം പ്രോഗ്രാമുകള്‍ ഇന്‍സ്റ്റാള്‍ ചെയ്യുന്നതിന്റെയുമൊക്കെ ചെലവ് ലാഭിക്കാം. ക്ലൗഡ് സമ്പ്രദായത്തിലൂടെ പ്രവര്‍ത്തിക്കുന്നതിനാല്‍ കമ്പനിക്കാവശ്യമായ പ്രോഗ്രാമുകളൊക്കെ ഇതിലൂടെ എളുപ്പത്തില്‍ ആക്‌സസ് ചെയ്യാം. യാത്രകള്‍ക്കിടയില്‍ എവിടെനിന്നെങ്കിലും ഒരു മോണിട്ടര്‍ തപ്പിപ്പിടിച്ചാല്‍ സ്വന്തം കമ്പ്യൂട്ടര്‍ പോലെ അതുപ്രവര്‍ത്തിപ്പിക്കാം. 

2.3 ജിഞ്ചര്‍ബ്രെഡ് വെര്‍ഷന്‍ തൊട്ടുള്ള ഏത് ആന്‍ഡ്രോയിഡ് ഫോണിലും ‘ഉബുണ്ടു ഫോര്‍ ആന്‍ഡ്രോയിഡ്’ സോഫ്റ്റ്‌വെയര്‍’ പ്രവര്‍ത്തിക്കും. ഒരു ജിഗാഹെര്‍ട്‌സ് എങ്കിലുമുള്ള ഡ്യുവല്‍ കോര്‍ പ്രൊസസറും 512 എം.ബി. റാമും വേണമെന്നുമാത്രം. കമ്പ്യൂട്ടര്‍ മോണിറ്ററിന് വീഡിയോ ഔട്ട്‌ലെറ്റ് നല്‍കാന്‍ എച്ച്ഡിഎംഐ ഔട്ട്പുട്ട്, വയര്‍ലെസ് മൗസും കീബോര്‍ഡും പ്രവര്‍ത്തിപ്പിക്കാന്‍ യുഎസ്ബി എന്നിവയും അത്യാവശ്യമാണ്. 

ഉബുണ്ടു ഫോര്‍ ആന്‍ഡ്രോയിഡ്’ സോഫ്ട്‌വേര്‍ പ്രവര്‍ത്തിപ്പിക്കുന്ന ആദ്യഫോണ്‍ ഏതു കമ്പനിയാണ് പുറത്തിറക്കുകയെന്ന കാര്യം വ്യക്തമാക്കാന്‍ ഷട്ടില്‍വര്‍ത്ത് തയ്യാറായില്ല. എന്നാല്‍ ഈ വര്‍ഷം അവസാനത്തോടെ ഈ സങ്കേതമുള്ള ഫോണുകള്‍ വിപണിയിലെത്തുമെന്ന് അദ്ദേഹം ഉറപ്പിച്ചു പറയുന്നു. സോഫ്ട്‌വേറിന്റെ പൂര്‍ണവികസനത്തിനായി അല്പം കൂടി ജോലികള്‍ ബാക്കിയുണ്ടെന്ന് ഷട്ടില്‍വര്‍ത്ത് സൂചിപ്പിച്ചു. സോഫ്റ്റ്‌വെയര്‍ സുരക്ഷിത്വത്തിന്റെ കാര്യത്തിലാണ് കാര്യമായി ശ്രദ്ധിക്കാനുള്ളത്. പക്ഷേ ലിനക്‌സ് സിസ്റ്റത്തില്‍ പ്രവര്‍ത്തിക്കുന്നതിനാല്‍ അക്കാര്യത്തില്‍ ആശങ്കകള്‍ക്കൊന്നും വകയില്ലെന്നും ഷട്ടില്‍വര്‍ത്ത് പറഞ്ഞു. 

സ്മാര്‍ട്‌ഫോണിനെ സിപിയു ആക്കിക്കൊണ്ട് കമ്പ്യൂട്ടര്‍ പ്രവര്‍ത്തിപ്പിക്കുകയെന്ന ആശയം പുതിയതൊന്നുമല്ലെന്നതാണ് രസകരമായ വസ്തുത. ആന്‍ഡ്രോയിഡിന്റെ ഇറങ്ങാന്‍ പോകുന്ന 5.0 വെര്‍ഷനില്‍ ഈ സൗകര്യമുണ്ടാകുമെന്ന് നേരത്തേതന്നെ വാര്‍ത്തകള്‍ വന്നതാണ്. പാഡ്‌ഫോണ്‍, ട്രാന്‍സ്‌ഫോര്‍മര്‍ എന്നീ ലാപ്‌ടോപ്പുകളില്‍ അസ്യുസ് കമ്പനി ഈ സംവിധാനം നേരത്തേ അവതരിപ്പിച്ചുകഴിഞ്ഞു. ലാപ്‌ഡോക്ക് എന്ന പേരില്‍ മോട്ടറോളയും ഇതു മുമ്പേ കൊണ്ടുവന്നിരുന്നു. എന്നാല്‍ അവയെല്ലാം കാശുകൊടുത്തു വാങ്ങേണ്ട ഹാര്‍ഡ്‌വേറുകളായിരുന്നു. എന്നാല്‍ അയ്യായിരം മുതല്‍ പതിനായിരം രൂപ വരെ മുടക്കി മോണിട്ടറും കീബോര്‍ഡും മൗസും വാങ്ങിയാല്‍ ഒരു ആന്‍ഡ്രോയ്ഡ് ഫോണുടമയ്ക്ക് കമ്പ്യൂട്ടര്‍ സ്വന്തമാക്കാനാകും എന്നതാണ് ഉബുണ്ടു ഫോര്‍ ആന്‍ഡ്രോയിഡ്’ സംവിധാനത്തിന്റെ പ്രയോജനം.

By beatsoftech

A Simple Idea To Make Text Chat Web Application

Hello and welcome.

In this tutorial we will learn about the basics of text chat.
And to do that, we will use a simple idea for text chat box routines.

Before you start:
We will use multiple programming languages in this tutorial, so please make sure before you start that you know:
1-The basics of HTML elements and Objects.
2-The basics of CSS to create a simple layout for the chat box elements.
3-Intermediate skills in Javascript to control all the chat box functionality (client side).
4-Intermediate skills in php to process incoming and outgoing information (server side).

And we will use an Ajax script to create a connection between the Server and Clients.
So I will use Ajax snippet I posted here before.
And that Ajax snippet will allow you to call another function when the server responses.

Now let’s get into work:
What are the procedures to accomplish a basic chat?

To do List:
– Create the user interface.
– Style user interface.
– Coding Client/Server.

Creating user interface :(index.htm)
Within the document’s body we need to add:
1-Form for Sign-in / Sign-out operations and let’s give it an id and set it to “signInForm”
Inside that form create the following elements and give it the associated id
Element id
———- —
Textbox “userName”
Submit button “signInButt”
Span “signInNmae”

Now, since I decided to use the same button for signing in and out I will give that button a name and I will change it accordingly.
That’s why I’ll give the submit button a name=”signIn” as initial value.

2-Div element to view the messages, give it id=”chatBox”
3-Div element to show currently online users, give it id =”usersOnLine”.
4-Another Form to handle message submitting, give it id =”messageForm” that contains the following elements:

Element id
———- —
Textbox “message”
Submit button “send”
Div “serverRes”

01 <html>
03 <head>
04 <title>DIC ChatBox Beta 1</title>
05 </head>
07 <body>
09 <h1></DIC> Chat Box</h1>
10 <form id="signInForm">
11     <input id="userName" type="text">
12     <input id="signInButt" name="signIn" type="submit" value="Sign in">
13     <span id="signInName">User name</span>
14 </form>
16 <div id="chatBox"></div>
18 <div id="usersOnLine"></div>
20 <form id="messageForm">
21     <input id="message" type="text">
22     <input id="send" type="submit" value="Send">
23 <div id="serverRes"></div>
24 </form>
25 </body>
26 </html>

That’s all elements we need, let’s save our HTML document as “index.htm”.

Creating the style sheet: (cb_style.css)
Let’s make it simple and clean so everyone else can edit it easily.
We will style each element depending on its id

Here is the CSS we need, it’s very simple so no need to add any comment

01 #signInForm, #messageForm {
02     margin:0px;
03     margin-bottom:1px;
04 }
05 #userName {
06     width: 150px;
07     height: 22px;
08     border: 1px teal solid;
09     float:left;
10 }
11 #signInButt {
12     width: 60px;
13     height: 22px;
14 }  
15 #signInName{
16     font-family:Tahoma;
17     font-size:12px;
18     color:orange;
19 }
20 #chatBox {
21     font-family:tahoma;
22     font-size:12px;
23     color:black;
24     border: 1px teal solid;
25     height: 225px;
26     width: 400px;
27     overflow: scroll;
28     float:left;
30 }
31 #usersOnLine{
32     font-family:tahoma;
33     font-size:14;
34     color:orange;
35     border:1px teal solid;
36     width:150px;
37     height:225px;
38     overflow:scroll;
39     margin-left:1px;
40 }
41 #message {
42     width: 350px;
43     height: 22px;
44     border: 1px teal solid;
45     float:left;
46     margin-top:1px;
47 }
48 #send {
49     width: 50px;
50     height: 22px;
51     float:left;
52     margin:1px;
53 }
54 #serverRes{
55     width:150px;
56     height:22px;
57     border: 1px teal solid;
58     float:left;
59     margin:1px;
60 }

Save that style as “cb_style.css” to same directory where we saved the index.htm before.

Now, we need to link the index.htm with cb_style.css.
At the document’s header part add this code

1 <link rel="stylesheet" type="text/css" href="cb_style.css">

Take a look at the screen shot it must be similar, if not please make sure that you typed the previous code correctly.

Resized to 83% (was 607 x 491) – Click image to enlargeAttached Image

After we finished working on the HTML elements and the style we’ll work on coding these elements to do what it has to do.

In this part we will code the client side in javascript and the server side in php

As everybody knows there are 4 basic procedures in every text chat application which are:
1- Signing in 2- Sending messages 3- Updating user’s data 4- Signing out
And of course we need some interface to transfer the data between the client and the server

Here I will use XMLHTTP request which is known as AJAX

I’m not going to talk about Ajax and how it works, so I will use an old snippet of Ajax that I posted here.

I will just mention its syntax
To send data we just call the Ajax function, give it the sending method(“GET”/”POST”),”the requested URL”,”data as name=value pairs”,the function handler that will receive the server response)

1 Ajax_Send("POST","my_url","name1=ahmad&name2=511",reponseFunc);

Save the snippet in the same directory and rename it to “ajax.js”
So let’s link this snippet to the index.htm like this:
In the document header add this code

1 <script type="text/javascript" src="ajax.js"></script>

Client side: (chatBox.js / hideShow()): Function
First create the function “hideShow(hs)” that will control signInForm and messageFrom visibility
We need to pass a string parameter to show/hide forms accordingly.
By default we want the messageForm to be hidden, that’s so we need to pass the function “show” as parameter that will hide the signInForm and show the messageForm
The name/value attributes of signInButt and the signInName will change too.

And when we pass it “hide” the things will go reverse
Open a new text document and type our hideShow() function

01 function hideShow(hs){
02 if(hs=="hide"){
03 signInForm.signInButt.value="Sign in"
07 signInName.innerHTML=""
08 }
09 if(hs=="show"){
10 signInForm.signInButt.value="Sign out"
14 signInName.innerHTML=signInForm.userName.value
15 }
16 }

Save the file as “chatbox.js” to the same directory we already working in
Open the index.htm file and link “chatbox.js” to it by adding this code in the document’s header

1 <script type="text/javascript" src="chatbox.js"></script>

As we said before we need the meesageForm to be hidden by default so edit the body tag to call hideShow() function to hide the messageForm on body’s load event like this

1 <body onload="hideShow('hide')">

Create two empty text files:
“onlineusers.txt” will store the already signed in users
“room1.txt” will store the recently sent messages (last 20 in our case)
Make sure that the tow files are having write permission.

Take a look at the flowchart in each procedure, it will give you a better understanding about how things are goes.

Part#1: Singing in

Resized to 97% (was 519 x 799) – Click image to enlargeAttached Image

Client side: (chatbox.js / signInOut()): Function
User will enter the user name he want and hit [signInButt] which has “signIn” as name’s value right now
The [signInForm] form will call the function [signInOut()] on submit event and exit.
[signInOut()] function will validate the user name for existing spaces (you can add any validation rules at this part.

The function will check the [signInButt] name if it’s equal to “signIn” (which already is)
If so, collect the user name and the sign in operation as name=value pairs
Send the data to server-side script “users.php” and let the Ajax to call [checkSignIn] function on server response.
Exit the function

01 // Sign in and Out
02 function signInOut(){
03 // Validation
04 if (signInForm.userName.value=="" || signInForm.userName.value.indexOf(" ")>-1){
05 alert("Not valid user name\nPlease make sure your user name didn't contains a space\nOr it's not empty.");
06 signInForm.userName.focus();
07 return false;
08 }
10 // Sign in
11 if ("signIn"){
12 data="user=" + signInForm.userName.value +"&oper=signin"
13 Ajax_Send("POST","users.php",data,checkSignIn);
14 return false
15 }
16 }

Server side: (users.php)
users.php will load the “onlineusers.txt” file to $onlineusers_file using built in (file) function which will converts the file to an array
Check if the client sent the user and the oper variables
If so, search the $onlieusers_file if the sent user name is exist, if so get the user index
If the operation is “signin” and user is not exist, add this user to $onlineusers_file array 
Call the function [saveUsers()] to save the changes.
Send the “signin” string to the client and exit

If the user is exist send the “userexist” string to the client and exit

The [saveUsers()] function will receive an array
Open the onlineusers.txt file for over writing
Lock the file
Write the array elements with linefeed character
Unlock the file
Close the file

01 function saveUsers($onlineusers_file){
02 $file_save=fopen("onlineusers.txt","w+");
03 flock($file_save,LOCK_EX);
04 for($line=0;$line<count($onlineusers_file);$line++){
05 fputs($file_save,$onlineusers_file[$line]."\n");
06 };
07 flock($file_save,LOCK_UN);
08 fclose($file_save);
09 }
11 $onlineusers_file=file("onlineusers.txt",FILE_IGNORE_NEW_LINES);
12 if (isset($_POST['user'],$_POST['oper'])){
13 $user=$_POST['user'];
14 $oper=$_POST['oper'];
15 $userexist=in_array($user,$onlineusers_file);
16 if ($userexist)$userindex=array_search($user,$onlineusers_file);
18 if($oper=="signin" && $userexist==false){
19 $onlineusers_file[]=$user;
20 saveUsers($onlineusers_file);
21 echo "signin";
22 exit();
23 }
25 if($oper=="signin" && $userexist==true){
26 echo "userexist";
27 exit();
28 }
29 }

After the user.php sent the data, the Ajax will detect server response and execute the function we specified [checkSignIn()]

Client side: (chatbox.js / checkSignIn()) Function:
The function will read the server response text (res)
If the server response is “userexist” the function will alert the user to change his sign in name
If response text is equal to “signin” that means the user name was accepted and it’s ready to use
Call [hideShow()] function to hide the [signInForm] and show the [messageForm]
And the [hideShow()] function now will set the name of the [signInButt] to “signOut” and its value to “Sign out” to be used in signing out procedure
Create an interval [updateIntrerval] to call each 3 seconds a new function we will create later [updateInfo()] which will handle the update of online users and sent messages.
Show “Sign in” notification in the [serverRes] DIV

01 // Sign in response
02 function checkSignIn(res){
03 if(res=="userexist"){
04 alert("The user name you typed is already exist\nPlease try another one");
05 return false;
06 }
07 if(res=="signin"){
08 hideShow("show")
10 messageForm.message.focus()
11 updateInterval=setInterval("updateInfo()",3000);
12 serverRes.innerHTML="Sign in"
13 }
14 }

Part#2: Sending messages
Attached Image

Client side: (chatbox.js / sendMessage()) Function
The user types a message in the [message] text box and hit [send] button
The form submit event will call the [sendMessage()] function
The function will collect the user name and the message in one string as name=value pairs
Use Ajax to send the data to “send.php” script on the server and call the function [sentOk] when server response

1 // Send message
2 function sendMessage(){
3 data="message="+messageForm.message.value+"&user="+signInForm.userName.value
4 serverRes.innerHTML="Sending"
5 Ajax_Send("POST","send.php",data,sentOk)
6 }

Server side: (send.php)
send.php receives the message and strips the HTML/PHP tags and slashes right away 
Receives the user too
Load the room1.txt file into $room_file and convert it to array using built in(file) function.
Create a new array element that contain the server time at the beginning, the string “<!@!>” as separator, the user name , “: ” and the message
Note: “<!@!>” has no meaning, it’s just a string we think that it will never occurs in the messages and we will use it again to separate the server time from the messages

Check if the $room_file array element’s count is greater than 20(last 20 recently sent messages), when it’s true remove the first elements in the array (the oldest message), and that’s will work just like a buffer for the sent messages

The number (20) means that the maximum number of messages that the client can receive in each update is 20
So maximizing this number will provides more messages buffer size

Anyway, send.php will open the “room1.txt” file for over writing now
Lock the file
Write the array’s elements with line feed character 
Unlock the file
Close the file
Send “sentok” string to the client which will be received by [sentOk()] function that will execute on server response.

01 $message=strip_tags($_POST['message']);
02 $message=stripslashes($message);
03 $user=$_POST['user'];
05 $room_file=file("room1.txt",FILE_IGNORE_NEW_LINES);
07 $room_file[]=time()."<!@!>".$user.": ".$message;
08 if (count($room_file)>20)$room_file=array_slice($room_file,1);
09 $file_save=fopen("room1.txt","w+");
10 flock($file_save,LOCK_EX);
11 for($line=0;$line<count($room_file);$line++){
12 fputs($file_save,$room_file[$line]."\n");
13 };
14 flock($file_save,LOCK_UN);
15 fclose($file_save);
16 echo "sentok";
17 exit();

Save the file as “send.php” to the same directory we are working in

Client side: (chatbox.js / sentOk()) Function
The function check if the response text is “sentok”
If so, clear the [message] text box value
Set the focus the [message] text box
Show the notification “Sent” in the [serverRes] DIV

If the server response is not equals to “sentok” the function will show “Not sent” in the [serverRes] DIV

01 // Sent Ok
02 function sentOk(res){
03 if(res=="sentok"){
04 messageForm.message.value=""
05 messageForm.message.focus()
06 serverRes.innerHTML="Sent"
07 }
08 else{
09 serverRes.innerHTML="Not sent"
10 }
11 }

Part#3: Updating user’s data
Here we have two types of the data we need to update (online users and the messages)
If you still remember, we create the [updateInterval] after sign in procedure done, and this interval will call the [updateInfo()] function every 3 seconds

Client side: (chatbox.js / updateInfo()) Function
Show the “Updating” string in the [serverRes] DIV
Use Ajax to call “user.php” script on server with no data to send and direct it to call [showUsers()] function on server response
Use Ajax to call “receive.php” on the server and send the variable lastReceived then call [showMessages()] function on server response

Now before we write this function we need to define the lastReceived variable out side the function making it have a global scope which will allow us to change/read its value from within [updateInfo()] and [showMessages()] functions
And maybe you will use it as a counter for the received messages
So at the top part of [chatbox.js] and outside any function let’s add this:

1 lastReceived=0

And here is the function

1 // Update info
2 function updateInfo(){
3 serverRes.innerHTML="Updating"
4 Ajax_Send("POST","users.php","",showUsers)
5 Ajax_Send("POST","receive.php","lastreceived="+lastReceived,showMessages)
6 }

Updating online users:
Attached Image

Server side: (users.php)
When the user.php receives nothing from the client it will load the onlineuser.txt file to $onlineusers_file array
Join that array with the string “<br>” and then send the joined array to the [sowUsers()] function on the client’s machines

Open the users.php file and add these two lines to it (at the bottom)

1 $olu=join("<br>",$onlineusers_file);
2 echo $olu;

Save the file 

Client side: (chatbox.js / showUsers()) Function
This function will receive the online-users joined array from the server and display it as it is inside the [usersOnLine] DIV

1 // update online users
2 function showUsers(res){
3 usersOnLine.innerHTML=res
4 }

Updating messages:
Attached Image

Server side: (receive.php)
receive.php will receive the lastreceived variable from the client and assign it to $lastreceived
Load the room1.txt file to $room_file array
Loop all over the array elements
Read each element and split the server time from the message (using the “<!@!>” string we added before) to $messageArr
Now the message time is $messageArr[0] and the username with the message is $messageArr[1]
Check if the message time > $lastreceived then send this message with HTM line break tag to the client because he didn’t receive it yet. (Depending on the lastreceived time the client sent)
After loop is done, send “<SRVTM>” string and the $messageArr[0] (which is now carry the last message’s time) to the client

Note: the string “<SRVTM>” has no meaning, we will just use it to separate the messages from the last message received time

1 $lastreceived=$_POST['lastreceived'];
2 $room_file=file("room1.txt",FILE_IGNORE_NEW_LINES);
3 for($line=0;$line<count($room_file);$line++){
4 $messageArr=split("<!@!>",$room_file[$line]);
5 if($messageArr[0]>$lastreceived)echo $messageArr[1]."<br>";
6 }
7 echo "<SRVTM>".$messageArr[0];

Save the file as “receive.php” to the same directory we are working in.

Client side: (chatbox.js / showMessages()) Function
The function will receive a string with all messages connected together with “<br>” and the last element is the last message time and it’s connected with “<SRVTM>”
First, we will clear the [serverRes] DIV
Then we split the last received time from the messages into msgTmArr array using the string “<SRVTM>”
Now we have array with two elements:
msgTmArr[0] contains all none received yet messages
msgTmArr[1] contains the last message’s time that delivered to the client

Now Assign the msgTmArr[1] to lastReceived variable (that we defined it before),so we will use it again in the next [updateInfo()] call
Create a new HTML span element to contain the received messages
Insert the msgTmArr[0] in the Span inner html
Append the span to the [chatbox] DIV
Update the [chatbox] DIV vertical scroll bar to show the last inserted line

01 // Update messages view
02 function showMessages(res){
03 serverRes.innerHTML=""
04 msgTmArr=res.split("<SRVTM>")
05 lastReceived=msgTmArr[1]
06 messages=document.createElement("span")
07 messages.innerHTML=msgTmArr[0]
08 chatBox.appendChild(messages)
09 chatBox.scrollTop=chatBox.scrollHeight
10 }

Part#4: Signing out
Attached Image

Client side: (chatbox.js / signInOut()) Function
User click on the singInButt (its value now is “Sign out” and its name is “signOut”)
The [signInForm] will call the [signInOut()] function and now the signInButt has the name “signOut”
The function will check the user name validation. (The validation is useless here because the user is passed this validation when he signed in)
The function will check if the signInButt name is equals to “signOut”
Collect user and oper data
Send the data using Ajax to users.php and tell Ajax to execute [checksignOut()] function on server response

Inside the [signInOut()] function and just before closing brackets add this code:

1 // Sign out
2 if ("signOut"){
3 data="user=" + signInForm.userName.value +"&oper=signout"
4 Ajax_Send("POST","users.php",data,checkSignOut);
5 return false
6 }

Server side: (users.php)
users.php will load the onlineusers.txt file to $onlineusers_file array
Receive the user and oper variables from the client
Search the array if the user exists; if so get its index
Check if the oper is equals to “signout” and the user is exist
If so, splice the user from the array
Send “signout” string to the client 
If the user not exists send “usernotfound” to the client and exit.

Open the users.php file and add this code after the part of the sign in procedure (before the closing bracket of (if isset) statement)
So if the sign in and out check failed, we will then join the array and send it back to the client

01 if($oper=="signout" && $userexist==true){
02 array_splice($onlineusers_file,$userindex,1);
03 saveUsers($onlineusers_file);
04 echo "signout";
05 exit();
06 }
08 if($oper=="signout" && $userexist==false){
09 echo "usernotfound";
10 exit();
11 }

Client side: (chatbox.js / checkSignOut())
The [checkSignOut()] function reads the server response and if it’s equals to “usernotfound” show “Sign out error” in the [serverRes] DIV and change the response text to “signout”
If the server response text is equals to “signout”, hide the [messageForm] and show the [signInForm]
Clear the updateInterval
Show “Sign out” string in [serverRes] DIV
Note: the [hideShow()] function will rename the signInButt to “signIn” and chage its value to “Sign in” too

01 // Sign out response
02 function checkSignOut(res){
03 if(res=="usernotfound"){
04 serverRes.innerHTML="Sign out error";
05 res="signout"
06 }
07 if(res=="signout"){
08 hideShow("hide")
09 signInForm.userName.focus()
10 clearInterval(updateInterval)
11 serverRes.innerHTML="Sign out"
12 return false
13 }
14 }

One other thing we have to do
If the user leave the site he must sign out automatically, that’s so we will call the [signInOut()] function on unload or on beforeunload event
And to do that we have to change the [signInButt] name to”signOut” then we call the function [signInOut()]
Edit the document’s body tag to be like this:

1 <body onbeforeunload="'signOut';signInOut()"onload="hideShow('hide')">

And that’s all

You must have now 9 files:

Again make sure that you have write permission on the onlineusers.txt and room1.txt

Upload those files and brows index.htm

This tutorial is based on a simple idea and it’s for learning purposes only
And it needs more enhancements before you can use it for real work. (adding user registration, administrators control panel, more validation rules,…)

Now I guess you can edit that code to make it use multiple chat rooms.

I hope it helps somebody to get the basics of text chat.

Download all files here Attached File (3.9K)

By beatsoftech

Google doodles a wave for Heinrich Rudolf Hertz’s 155th birthday

The Google logo takes the form of electromagnetic waves (in Google colours – blue, red, yellow and green) to pay tribute to German physicist Heinrich Rudolf Hertz on his 155th birth anniversary. Hertz was born at Hamburg on February 22, 1857.

Hertz was the first to broadcast and receive radio waves. His pioneering work laid the way for the development of radio, television and radar.

The unit of frequency of a radio wave – one cycle per second – is named the hertz, in honour of Heinrich Hertz.

Google doodles a wave for Heinrich Rudolf Hertz's 155th birthday

Hertz proved the existence of radio waves in the late 1880s. He used two rods to serve as a receiver and a spark gap as the receiving antennae. Where the waves were picked up, a spark would jump. Hertz showed in his experiments that these signals possessed all of the properties of electromagnetic waves.

With this oscillator, Hertz solved two problems. First, timing English scientis James Clerk Maxwell’s waves. He had demonstrated, in the concrete, what Maxwell had only theorised – that the velocity of radio waves was equal to the velocity of light. (This proved that radio waves were a form of light).

Second, Hertz found out how to make the electric and magnetic fields detach themselves from wires and go free as Maxwell’s waves.

Hertz died at the young age of 36 on New Year’s Day 1894. There is a lunar crater on the dark side of the Moon named after him.

Unlike recent Google doodles that used complex JavaScript for animated doodles, the Hertz Google doodle is a relatively simpler animated GIF image.

Google has, till the Hertz doodle, posted 1308 doodles on its home page since the first ever Google doodle back on August 30, 1998.


By beatsoftech

Windows 8 to feature improved accessibility features

 Windows 8 will feature improved accessibility features, making it easier to use for those visual impairment or other disabilities. The new features have been shown off on the Building Windows Blog, in a post by Jennifer Norberg, senior program manager of the Human Interaction Platform team.

Other touch-based accessibility features, destined for tablets and touchscreen monitors, will allow users to use various types of magnifier zoom with different gestures, and on screen Plus and Minus buttons. Narrator can also be accessed by tapping specific areas of a screen, and types of icons.

The biggest change that Microsoft will bring with Windows 8 are the Metro UI style apps, and the company wants to ensure users with disabilities will be able to enjoy them as well. The Metro UI also gives developers the opportunity to present accessibility settings in a new way, with key settings displayed in a manner that was easy to use. Settings will include simplified toggles for high contrast, size of UI elements, and DPI scaling.

The blog post admitted that Windows still has a long way to go to completely meet the needs of people with disabilities, but the new OS will be making many new steps to that end. Microsoft will be providing standard developer tools with baseline accessibility features built-in, to ensure most apps in the Windows Store will be accessible. New tools and guides will also be available. The company will be engaging assistive technology vendors (ATVs) as well, urging them to adopt Windows 8 and build upon the accessibility scenarios.

An accessibility filter for the Windows Store will also be available, helping users find only those apps with the features built in. The Windows Store will also feature a special comments and ratings section, to let other users know which are the best apps, and to give developers feedback on their products.     

Norberg added: “If you are a user with accessibility needs, we think you will like what we have done. If you are a developer, build an accessible app and reach a larger spectrum of users! If you are an AT (assistive technologies) vendor, come work with us and refresh your applications using our platform. This is an exciting and compelling release that will change how people of all abilities interact with PCs.”

For more information, check out the Building Windows 8 blog post

Narrator main screen to configure settings


Drag your finger along the border to move around the screen. Borders disappear when you reach the edge of the screen.


Tap on two opposing borders at the same time. Full screen preview highlights where you are on the screen.


By beatsoftech


If Hackintosh is not new to you, you will have no problem to follow along with this guide. If you are new to this “Hackintosh” thing, don’t worry this isn’t the real Hackintosh and installing on a Virtual Machine meaning it doesn’t matter what you do, you can always recover or start from scratch again without damaging your perfectly working Windows 7 environment.

To start, here are the following tools and items you need to have:

  • VMware Workstation 7.1+ (get the latest version) or even better free version of VMware Player will work as well
  • After many readers’ respond, it looks like it’s a good idea to download and install VMware Workstation even with a free trail, for initial setups. Afterwards you can use VMware Player to run the VM.
  • Download the Mac OS X VMware unlocker  Mac OS X VMware unlocker mirror1mirror2and other helper  ([UPDATE] VMware unlocker link)
  • Download the Audio / Sound driver for VMware Mac OS X Lion if you want to get audio working as well (thanks to Manas commentator)
  • Download the bootable “Mac OS X Lion bootable vmdk” (find it on Google should be around 4.12GB in size)
  • At least 4GB of RAM
  • At least 40 GB of Hard Drive space

Make sure you have the above tool ready, after you’ve installed VMware workstation run the Mac OS X VMware unlocker


Pick a location to extract the file.

Go to the location you’ve just extracted the file. should be something like this  \Mac OS X Lion VMware Files\VMware Unlocker – Mac OS X Guest

shift + right click on the folder “VMware Workstation Unlocker –Windows” to “Open command window here”


Run “windows.bat” command


When this is done you should see something like the above screenshot.

Now navigate back to the folder \Mac OS X Lion VMware Files\Mac OS X Lion find the named Mac OS X Lion.vmx and double click.


This will open the VMware Workstation, you should see something like the following


Now click Edit virtual machine settings


Here you want to add a new hard disk which will contain the vmdk you’ve just downloaded. Click “Add..” select “Hard Disk” Click next


Select “Use an existing virtual disk”


Browse and find the vmdk file, click “Open”


Click “Finish” when you done.

The reason you want to add another hard drive is that in the original setting, the 40GB has no OS on it, therefore VMware will try to boot off the OS from the second disk (the vmdk file) which will load and boot into Lion Installer.


Now back to the main menu, click “Power on the virtual machine”

From now here just following the on screen instruction to install Mac OS X Lion. Should be pretty straight forward.

When you done installing Mac OS X Lion on the Virtual Machine, go download the VMware tools inside the new Mac OS X Lion


Double click “Install VMware Tools”


After you finish installing the VMware tools, reboot the machine now you should have nativescreen resolutions.


From now on, it’s highly suggested to take a snapshot of the working VM. Incase in the future you done anything that messed up the machine you can always rollback to previous working state with the save of snapshot. From this moment on, you can also remove the second hard drive (the bootable Lion installer vmdk file) that you’ve added to the VM earlier.

Update to 10.7.1

You should be able to install the 10.7.1 update without an issue.

WarningPlease ONLY update to 10.7.1 and take a snapshot of your working systemBEFORE any attempts update to the latest 10.7.2 update release, which will likely cause kernel panic. You can download the update patch to 10.7.1 here

Update to 10.7.2

Here are the steps to enable your VM successfully update to the latest 10.7.2 Lion which includes iCloud and many other integrations. (Thanks to one of our commentator Jay)

1. Download the 10.7.2 combo update from Apple’s website, don’t try to update it from Software Update.

2. Don’t apply the update yet, make sure you have taken the snapshot of your current system

3. Open Terminal inside Lion

4. run the following command, including the dot at the end.

cp -r /System/Library/Extensions/AppleLSIFusionMPT.kext .

5. Now apply the update, but don’t reboot after it’s finished.

6. now go back to terminal and at the same directory location run the following command

7. sudo rm -rf /System/Library/Extensions/AppleLSIFusionMPT.kext

8. sudo cp -r AppleLSIFusionMPT.kext /System/Library/Extensions

9. reboot


Update to 10.7.3

1. Make sure you have updated your VM to 10.7.2 before proceed.

2. Download the OS X Lion update 10.7.3 here (don’t download the combo update)

3. Take a snapshot before update

4. Repeat step 3-9 from previous steps in 10.7.2 update and you are good to go.

Note: Things you need to know, in order to keep your VMware Lion Hackintosh up to date, you need to apply update one at a time. Ex, from a fresh install image, you need to first apply 10.7.1 update, then when the update is successful, you need to update your VM to 10.7.2, and finally to 10.7.3. If you try to directly update to 10.7.3 using combo update it doesn’t seems to be working. Good luck !


Optional – Enable VMware Shared Folder

After you’ve had a fully working Lion you can enable the VMware share folder to your Windows 7 host machine. So this way the VM will have access to your Windows 7 file.

To do this, go to the “Virtual Machine Settings” when it was powered off.


Go under options tab, select “Shared Folders”

Pick “Always enable” and click “OK”


Go “Browse..” the folder that you wish to share to.


From here you can pick and choose to make the folder to be “Read-only” or “Enable this share”


That’s all there is. Finish the wizard and power on the VM again you should now see the mount folder on your Lion desktop that points to your Windows 7 shared folder.

Got Stuck ? Checkout The Basic Troubleshoot Guide

Over the last couple month there are large number of readers found this guide to be very useful detailed guide on such topic. However, there are also quite a few number of people experiencing issues with this install guide. Rather than try to answer the questions one by one, I’ve compiled a post dedicated on the topic, how to troubleshoot your hackintosh/VM Mac OS X.

If you are one of those who get stuck, it’s a good idea to check out the guide first BEFORE you try to leave a comment below.

Happy Virtual Machine !

By beatsoftech

Install OS X Snow Leopard in VMware Windows 7

The following step by step guide will help you in installing Mac OS X 10.6 Snow Leopard as a guest virtual machine in Windows 7. You’ll need to have a system with an Intel processor which supports hardware virtualization, original OS X Snow Leopard retail disk, VMware Workstation 7 and Windows 7, Vista or XP installed as host operating system. If you meet all these requirements, you can then install OS X Snow Leopard as a VM under Windows and can enjoy the best of both worlds.

Snow Leopard in Windows 7

Note: We don’t in anyway encourage downloading Apple software via file-sharing / torrent sites and run it in an virtualized environment under Windows. This guide is for informational purposes only. If you like OS X Snow Leopard, Get a Mac.

Step 1: Download and install VMware Workstation 7.

Step 2: Download pre-made modified version of Snow Leopard.vmdk and darwin_snow.iso files required to get this thing to work. Please don’t ask for the link to these files. You can find them easily elsewhere on the web.

Step 3: Start VMware Workstation and open up “Mac OS X Server 10.6 (experimental).vmx” file which you downloaded in Step 2.

Snow Leopard in VMware

Step 4: Click on”Edit virtual machine settings”, select CD/DVD (IDE) option from left hand side and then and select “Use ISO image file” option. Point it to “darwin_snow.iso” which you downloaded in Step 2.

Snow Leopard in VMware

Step 5: Now power on the virtual machine and hit “F8” key. You should now have a screen similar to the one shown below.

Snow Leopard in VMware

Step 6: Now you’ll have to point your virtual machine to OS X Snow Leopard retail DVD instead of “darwin_snow.iso”. To do this, right click on CD/DVD option found in lower right most corner of your VMware window and select settings.

Snow Leopard in VMware

Insert OS X Snow Leopard retail DVD in your DVD drive and select the “Use physical drive” option.

Step 7: Now go back and select “c” option (Boot DVD) from the prompt which you got in Step 5 to boot from the OS X retail DVD. OS X boot screen with Apple logo should now appear. If the boot screen doesn’t appear for you, try booting it in verbose mode by pressing “F8” key after selecting “c” option, and then enter “-v” (without quotes). This will enable the system to boot OS X DVD using verbose mode.

Snow Leopard in VMware

Step 8: Wait for a couple of minutes for the Installation Setup screen to show up. From here on, simply follow the onscreen setup instructions to install OS X Snow Leopard. Make sure you format your virtual hard drive in “Mac OS Extended (Journaled)” format using Disk Utility. Customize your installation with minimum set of printer drivers and language options for a lightweight trouble free installation experience.

Step 9: Once the installation is completed. System will automatically reboot. At this point, close your guest virtual machine and change your CD/DVD option again like you did in Step 2 to point it to “darwin_snow.iso”.

Step 10: Start the virtual machine again. Press “F8” key and select “h” option to “Boot first hard disk”. Voila! Snow Leopard should now be running live under Windows 7! [via ihackintosh]

Feel free to ask me any question should you run into any problem in getting Snow Leopard VM to work under Windows 7.

By beatsoftech

Apple to launch iPad 3 early next month

image description

Apple will launch the much-awaited iPad 3 at an event early next month, says an All Things D report. The successor of iPad 2 is reported to sport a more powerful processor and the much-hyped, Retina Display. The event is going to be held in San Francisco.

Apple typically releases its products annually. TheiPad 2 was launched in March last year, therefore, the reported schedule fits in. According to the All Things D report, Apple will put the iPad 3 on sale a week or two later after the official announcement. The report, however, does not reveal the exact launch date. The iPad 3 is also reported to have an improved graphics processing unit, and a 2048×1536 Retina Display.

The iPad 3 release report comes days after an alleged leaked photo of the new iPad hit the Internet. The image, which hinted that the device is already under production, triggered all sorts of speculation regarding the new iPad 3. It’s notable that the leaked photo showed very slight difference from the iPad 2, which means the image could be of a rejected prototype or even a fake one.

Another technology site The Verge reports that the new iPad will have double the screen resolution of the iPad 2 and would be one millimetre thicker. The device is likely to be powered by an dual-core A6 chip, and not quad-core as suggested by previous reports.

By beatsoftech