Monday, July 21, 2014

"Selenium 2 Testing Tools" - book review

In this post I will do a book review about a book called "Selenium 2 Testing Tools" written by David Burns. It is a beginners guide for Selenium 2 published 2012 by Packt © Publishing.

It is fairly new and it covers basic information about all aspects  of Selenium 2.
In 11 chapters and two appendices it manages to help reader get basic understanding about Selenium using code examples and little chapter quizzes. First of all you need to install necessary software like Java jdk, InteliJ Idea, selenium - server standalone, selenium IDE plugin for Firefox, Firebug and Firefinder.

Chapters:
  1. Getting started with Selenuim IDE, where you get the basics of using Selenium IDE Firefox plugin. Recording your own test case and test suites. Adding test comments. Asserting and verifying tests with Selenium commands. Using multiple windows and testing Ajax applications.
  2.  Locators, where you learn basic HTML element locating methods. Searching tag elements by ID, name, CSS selector, XPath, DOM and text link again using Selenium IDE. 
  3. Overview of Selenium WebDriver, where you get introductory text about creation of Selenium tools and how it is structured. 
  4. Design Patterns, where you use Page Object and Page Factory patterns to code your selenium tests. Also using LoadableComponents in your tests
  5. Finding Elements, where you use Java code, junit testing frameworks and Selenium WebDriver run tests for finding html elements by ID, name, XPath, CSS, DOM and link text. In Selenium API you find one html element or you can find a list of elements that cover certain criteria.
  6. Working with WebDriver, where you get know all basic drivers for each of the most popular browsers, Firefox, IE, Chrome, Opera and you do some basic Java tests. In this chapter I found that FirefoxDriver is part of Selenium WebDriver while IE and Chrome need additional libraries to run from selenium. As for Opera there is a library that covers only versions up until Opera 12.x built on presto engine. For newer versions there is still no support by Opera team(not sure, have to check). Libraries: selenium downloads, IE driver, IE driver downloadsChrome driver, Opera driver
  7. Mobile devices, where you get to test web applications that run in Android, iPhone and Opera Mobile browsers. Libraries: Selendroid (replacement for the obsolete AndroidDriver).
  8. Getting started with Selenium Grid, where you get to understand how to make selenium tests that run in parallel on several machines and on several browsers at the same time. Also on different operating systems, like Windows and Linux. So basically selenium server can be run as a grid hub, but also as a node. 
  9. Advanced user interactions, where you use selenium webdriver to run keyboard and mouse based tests. Also you will use Actions java class for performing sequence of mouse/keyboard actions which is handy. 
  10. Working with HTML5. In this chapter you are visiting application cache, browser connections (online/offline), WebStorage (local and session storage).
  11. Advanced topics. In this chapter you will learn, how to capture screenshots when error appears with selenium webdriver, use XVFB buffer to test application without interference with the tests (works only on Linux) and Browsermob Proxy to monitor web application traffic.
  12. Appendix A, Migrating from Remote Control to WebDriver
  13. Appendix B, Pop quiz answers
Some useful links:

http://www.packtpub.com/selenium-2-testing-tools-beginners-guide/book
http://book.theautomatedtester.co.uk/
http://docs.seleniumhq.org/
https://code.google.com/p/windowlicker/
http://bmp.lightbody.net/
https://media.readthedocs.org/pdf/browsermob-proxy-py/latest/browsermob-proxy-py.pdf
https://github.com/webmetrics/browsermob-proxy
http://stackoverflow.com/questions/944086/is-there-anything-like-xvfb-or-xnest-for-windows
http://en.wikipedia.org/wiki/Xvfb

According to my experience, it does what is meant to be, aka introducing selenium 2 trough examples and information. Apart from some code errors and obsolete tools like AndroidDriver which today is replaced by SelendroidDriver it is very well made book. If you are just starting with selenium 2 testing tools this is the book to choose. I give it 4.5/5

Perhaps this is the next good read, Selenium testing tools Cookbook,
Selenium WebDriver Practical Guide

Friday, July 11, 2014

"Ext JS 4 First Look" and "Mastering Ext JS" - book review

Hello. In this post I shall explain my thoughts on two books, Ext JS 4 First Look and Mastering Ext JS written by loiane Groner.

Ext JS 4 First Look

It is an intruductory book for Ext JS 4 framework, specifically version 4.2. You can find lot of comments and posts across the Internet about previous version of Ext JS 4, 4.0 and 4.1, it is said that were buggy. So my advice is use Ext JS 4.2 for your future projects. Not sure about Ext JS 5, it is a new release.

In about 300 pages Loiane managed to cover all aspects of Ext JS 4 framework. It has lot of useful information and you can get a general understanding about the framework's capabilities. However is a bit techincal, so I recommend reading each chapter at least twice. It also a good practice to try and write the code from the book on the a real machine and see how it works. From this point of view I think it needs more code examples. So if you want to learn Ext JS 4 framework, I think this book is a good start. 4/5

Mastering Ext JS

In this second book about Ext JS 4 you get to develop real world Ext JS 4 based application (using sakila sample database). It has lot of code and reading it is a bit dificult task since you need to understand what the code does. While reading it I set up my working environment and started coding from the book. It begins ok, all things that were necessary were covered in the book. However when you get deep into it like 150 pages which is middle of the book, you can clearly see that some application modules are not finished, or a code is missing. I managed to find code base here. It easens up things a little, if you copy code form github. But I also found that some php files had commented code and weren't working. It has a bit of inconsistency with the book. You get the feeling it is not made for beginner web developer :) I managed to find solutions to most of the problems while developing my practice app here: http://masteringextjs-practices.rhcloud.com/ but that was the case because I already knew PHP 5, firebug, MVC architecture, Aptana, JavaScript basics, html etc...

- still in development. Use vlado as user and 123456 as password to log in. You can change to different language, now English US and MK(Macedonian) available. If you get loading errors or it doesn't want to show up, refresh the tab. Still things to be done. 

Notes: 
  • Some php file had commented code out in the github package. Why should I bother understanding what the php code does when I learn Ext JS?
  • It happened to build a production version of the app and when uploaded to server it doesn't work as it works locally. Charts aren't drawn, login window stays after loging in, loading notification stays forever.  Not sure why it does that, a testing is neccesarry. Ok I set up Siesta as mentioned in chapter 12 - Debugging and Testing, I run the test from the book and get error Application.js not found in Firebug. :) Ok I deployed (prebuild app) masteringextjs4 zip package from github to my server and try the tests, some strange error appears, "j is undefined" :D So now I cannot test even the prebuilt application. Maybe I have missed to read some guide or whatever, but overall I am a bit lost as Ext JS beginner.
I give points for ingenuity. Really good use of available learning resources like Sakila sample database. You will get to work with MySQL db, MySQL Workbench, exporting/importing data. Also PhpMyAdmin which is a really good admin tool.

All in all it is a good book, but you will not learn much if you don't code the code yourself and try to debug yourself. It is very techincal and as I said cover each chapter twice. Once reading, once, coding. It contains lot of general information about Ext JS 4 and lot of advices about tools to develop. According to my experience reading it I give it 3.75/5

Thursday, July 25, 2013

Simple Gallery App in Android

I have recently worked on a simple Gallery application in Android.

It has one ImageView component, two buttons, previous and next and one TextView for description. It is a gallery application for European cars. Actually I have 27 car brands and one model (image) for each brand. I added 27 images which are all 640 x 480 pixels (You can download images from Google) into CarTestApp/res/drawable-mdpi folder.

I was testing my app on Nexus 7 AVD emmulator.

Here is how you application should look like.



I will show you some tricks I used in this small app, like how to access all drawable objects.

Ok so here is my layout file:



My strings.xml file

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">CartTestApp</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="image_view">Image description</string>
    <string name="prev_btn">prev</string>
    <string name="next_btn">next</string>
    <string name="car_name_text_view">Car Name</string>
</resources>


I added Utils.java file for a helper function. It is only one function but I guess I will expand the application future.

Utils.java:

package com.testpkg.carttestapp;

public class Utils {
    public static String formatFirstLetterOfString(String str) {
        String result = "";

        result = str.substring(0, 1).toUpperCase()
                + str.substring(1).toLowerCase();

        return result;
    }
}


Next class I added is called CarNames.java. It has many static functions so that I don't need to instantiate an object of this class. No need to.

Here it is:




Check these lines:

public static Field[] nativeDrawables = android.R.drawable.class
            .getFields();

public static Field[] drawables = com.testpkg.carttestapp.R.drawable.class
            .getFields();


Function getFields() returns the fields in a given resource from our application.

For example android.R.drawable contains native android drawable resources while com.testpkg.cartestapp.R.drawable contains drawable resources that we have added to our application.

So actually we can search our resources with code.

I have two ArrayList objects, one for drawable ids and one for drawable string names. I also have a hash map with drawable id as a key and car string name as a value.

Here is the reset() function in which I fill my lists and the hash map:

public static void reset() {

     for (Field field : drawables) {
            try {
                if (!field.getName().equals("ic_launcher")) {
                    carIdsList.add(field.getInt(field.getName()));
                    carStringsList.add(formatCarFieldName(field.getName()));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        for (int i = 0; i < carStringsList.size(); i += 1) {
            carNamesList.put(carIdsList.get(i), carStringsList.get(i));
        }
    }


You may noticed this function formatCarFieldName(); I can use java function toUpperCase() but that will make all letters upper case. I don't want that, I wan only the first letter upper cased. Strings are immutable values so I make a concatenation trick like this one:

result = str.substring(0, 1).toUpperCase() + str.substring(1).toLowerCase();

which will upper case only the first letter. You can find this in the Utils class.

Some screen shots:



Tuesday, July 16, 2013

Washing Machines App with images

I managed to improve the application by adding images of the machines to the project.

The complete source code is on git hub https://github.com/bluePlayer/practices/tree/master/WashingMachines

- I added 6 images for each machine brand: LG, Samsung, BSH, Gorenje, Whirlpool and Videocon into the res/drawable-mdpi. You can add in other drawable folders for different screen resolutions but for this small application this is enough.

Note: Images and data for the washing machines are arbitrary and therefore not correct. 

In details.xml I added this ImageView component

<ImageView
        android:id="@+id/machine_image"
        android:layout_marginTop="10dp"
        android:layout_marginLeft="40dp"
        android:contentDescription="@string/machineImageDescrp"
        android:layout_width="230dp"
        android:layout_height="200dp"
        android:src="@drawable/bsh" />


Here it is:


- I added this line in strings.xml for the image view description attribute

<string name="machineImageDescrp">Current machine image</string>

- I dynamically change the image resource id for appropriate machine.

In DetailsActivity.java like this

this.machineImage = (ImageView) findViewById(R.id.machine_image);       this.machineImage.setImageResource(this.setImageId(this.brandName.getText().toString()));      
where setImageId() changes the image id according to the brand name

private int setImageId(String brandNameStr) {
        int result = 0;
        if (brandNameStr.equals(WMConstants.LG)) {
            result = R.drawable.lg;
        }
        if (brandNameStr.equals(WMConstants.SAMSUNG)) {
            result = R.drawable.samsung;
        }
        if (brandNameStr.equals(WMConstants.BSH)) {
            result = R.drawable.bsh;
        }
        if (brandNameStr.equals(WMConstants.WHIRLPOOL)) {
            result = R.drawable.whirlpool;
        }
        if (brandNameStr.equals(WMConstants.VIDEOCON)) {
            result = R.drawable.videocon;
        }
        if (brandNameStr.equals(WMConstants.GORENJE)) {
            result = R.drawable.gorenje;
        }
        return result;
    }


- Now you can see some new class called WMConstants. It is a new class I added for the project to keep track of all constants because using constants is much easier than remembering many strings. And also immune to errors.

Here it is

package com.example.washingmachines;
public class WMConstants {
    public static final String LG = "LG";
    public static final String SAMSUNG = "Samsung";
    public static final String BSH = "BSH";
    public static final String WHIRLPOOL = "Whirlpool";
    public static final String GORENJE = "Gorenje";
    public static final String VIDEOCON = "Videocon";

    public static final String FRONT_TYPE = "front";
    public static final String TOP_TYPE = "top";
    public static final String HYBRID_TYPE = "hybrid";

    public static final String MACHINE_TYPE = "type";
    public static final String MACHINE_BRAND_NAME = "brandName";
    public static final String MACHINE_WEIGHT = "weight";
    public static final String MACHINE_MAX_RPM = "maxRpm";
    public static final String MACHINE_WASH_TEMP = "washTemp";
    public static final String MACHINE_HAS_ENERGY_STAR = "hasEnergyStar";
    public static final String MACHINE_POWER_USAGE = "powerUsage";
}


- Most of the files used are same as in previous tutorials but you can use them all from git hub link above without no problems as it has the latest version of this application.

Here is Details.java



- MainActivity.java



Here are some resulting images:

list of machines

Gorenje Details

Videocon details

Whirlpool details

I have added sample images in the assets folder. You can use them for your project or you can use your own images. They should be 230x200 pixels

Monday, July 15, 2013

Washing mashines app in two activities

I managed to separate the list of machines and the details into separated activities.
All is the same as before except details are opened into new window.

The next part would be to add image to be shown along with the details of each washing machine.

Again the data used for the machines is arbitrary so it is not 100% correct. Just for practising purpose.

My strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">WashingMachines</string>
    <string name="action_settings">Settings</string>
    <string name="machine_type">Machine type</string>
    <string name="brand_name">Brand name</string>
    <string name="weight">Weight</string>
    <string name="maxRpm">Max RPM</string>
    <string name="washTemp">Washing temperature</string>
    <string name="hasEnergyStar">Has energy star</string>
    <string name="powerUsage">Power usage</string>
    <string name="title_activity_details">MainActivity</string>
    <string name="main_list_btn">To the list</string>   
</resources>


activity_main.xml now has only list view component in linear layout for listing the available machines.

Here it is:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    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" >

    <ListView
        android:id="@+id/scroll_view"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    </ListView>

</LinearLayout>


A new layout is added for the DetailsActivity.java, details.xml.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    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=".DetailsActivity" >

            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/machine_type" />

                    android:id="@+id/machine_type_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/machine_type" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/brand_name" />

                    android:id="@+id/brand_name_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/brand_name" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/weight" />

                    android:id="@+id/weight_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/weight" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/maxRpm" />

                    android:id="@+id/max_rpm_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/maxRpm" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/washTemp" />

                    android:id="@+id/wash_temp_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/washTemp" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/hasEnergyStar" />

                    android:id="@+id/has_energy_star_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hasEnergyStar" />
   


            android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

                    android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/powerUsage" />

                    android:id="@+id/power_usage_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/powerUsage" />
   


           android:id="@+id/main_list_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/main_list_btn" />


It contains all the text fields for showing data about clicked machine from the main list. I used the wizard to add new android activity and it created details.xml layout file automatically.

Right click on your project node in Projects Tab -> New -> Other -> Android Activity

Name you new activity as you like I named it DetailsActivity and details.xml

Now about java classes.

WashingMachine.java stays the same as in previous post.

MainActivity.java look like this:

package com.example.washingmachines;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends Activity {

    private ListView machines = null;
    private List listOfMachines = new ArrayList();
    private ArrayAdapter adapter = null;
    private List machinesList = new ArrayList();
   
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {

        this.machines = (ListView) findViewById(R.id.scroll_view);

        WashingMachine wm1 = new WashingMachine("front", "LG", 65, 1200, 41,
                false, 100);
        this.listOfMachines.add(wm1);

        WashingMachine wm2 = new WashingMachine("top", "Samsung", 73, 800, 60,
                false, 90);
        this.listOfMachines.add(wm2);

        WashingMachine wm3 = new WashingMachine("hybrid", "BSH", 52, 1650, 36,
                true, 70);
        this.listOfMachines.add(wm3);

        WashingMachine wm4 = new WashingMachine("top", "Whirlpool", 105, 1400,
                56, false, 150);
        this.listOfMachines.add(wm4);

        WashingMachine wm5 = new WashingMachine("front", "Gorenje", 360, 2000,
                70, false, 300);
        this.listOfMachines.add(wm5);

        WashingMachine wm6 = new WashingMachine("hybrid", "Videocon", 300,
                2000, 85, false, 310);
        this.listOfMachines.add(wm6);

        this.machinesList.add(this.listOfMachines.get(0).getBrandName());
        this.machinesList.add(this.listOfMachines.get(1).getBrandName());
        this.machinesList.add(this.listOfMachines.get(2).getBrandName());
        this.machinesList.add(this.listOfMachines.get(3).getBrandName());
        this.machinesList.add(this.listOfMachines.get(4).getBrandName());
        this.machinesList.add(this.listOfMachines.get(5).getBrandName());

        this.adapter = new ArrayAdapter(this,
                android.R.layout.simple_list_item_1, this.machinesList);
        this.machines.setAdapter(adapter);

        this.machines.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView arg0, View arg1, int arg2,
                    long arg3) {
                Intent k = new Intent(MainActivity.this, DetailsActivity.class);
                k.putExtra("type", listOfMachines.get(arg2).getType());
                k.putExtra("brandName", listOfMachines.get(arg2).getBrandName());
                k.putExtra("weight", listOfMachines.get(arg2).getWeight());
                k.putExtra("maxRpm", listOfMachines.get(arg2).getMaxRpm());
                k.putExtra("washTemp", listOfMachines.get(arg2).getWashTemp());
                k.putExtra("hasEnergyStar", listOfMachines.get(arg2).isHasEnergyStar());
                k.putExtra("powerUsage", listOfMachines.get(arg2).getPowerUsage());
                startActivity(k);

            }
        });

    }

    @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;
    }

}


I create new Intent that launches DetailsActivity and put data from the clicked machine into the new intent using putExtra() method. Than I start the new activity

Intent k = new Intent(MainActivity.this, DetailsActivity.class);

k.putExtra("type", listOfMachines.get(arg2).getType());
                

k.putExtra("brandName", listOfMachines.get(arg2).getBrandName());
                

k.putExtra("weight", listOfMachines.get(arg2).getWeight());
               

 k.putExtra("maxRpm", listOfMachines.get(arg2).getMaxRpm());
               

 k.putExtra("washTemp", listOfMachines.get(arg2).getWashTemp());
                

k.putExtra("hasEnergyStar", listOfMachines.get(arg2).isHasEnergyStar());
                

k.putExtra("powerUsage", listOfMachines.get(arg2).getPowerUsage());
                

startActivity(k);

arg2 is the index of the clicked item in the list view.

Now the last class is DetailsActivity.java which read the extra data sent to it and fills the text views that reside inside it.

package com.example.washingmachines;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class DetailsActivity extends Activity {

    private TextView type = null;
    private TextView brandName = null;
    private TextView weight = null;
    private TextView maxRmp = null;
    private TextView washTemp = null;
    private TextView hasEnergyStar = null;
    private TextView powerUsage = null;
    private Button mainListBtn = null;
   
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.details);
      
        this.type = (TextView) findViewById(R.id.machine_type_view);
        this.brandName = (TextView) findViewById(R.id.brand_name_view);
        this.weight = (TextView) findViewById(R.id.weight_view);
        this.maxRmp = (TextView) findViewById(R.id.max_rpm_view);
        this.washTemp = (TextView) findViewById(R.id.wash_temp_view);
        this.hasEnergyStar = (TextView) findViewById(R.id.has_energy_star_view);
        this.powerUsage = (TextView) findViewById(R.id.power_usage_view);
      
        String typeValue = getIntent().getStringExtra("type");
        this.type.setText(typeValue);
      
        String brandNameValue  = getIntent().getStringExtra("brandName");
        this.brandName.setText(brandNameValue);
      
        String weightValue  = getIntent().getStringExtra("weight");
        this.weight.setText(weightValue);
      
        String maxRpmValue  = getIntent().getStringExtra("maxRpm");
        maxRmp.setText(maxRpmValue);
      
        String washTempValue  = getIntent().getStringExtra("washTemp");
        washTemp.setText(washTempValue);
      
        String hasEnergyStarValue = getIntent().getBooleanExtra("hasEnergyStar", false) ? "yes" : "no";
        hasEnergyStar.setText(hasEnergyStarValue);
      
        String powerUsageValue  = getIntent().getStringExtra("powerUsage");
        powerUsage.setText(powerUsageValue);
      
        this.mainListBtn = (Button) findViewById(R.id.main_list_btn);
        this.mainListBtn.setOnClickListener(new OnClickListener() {
          
            @Override
            public void onClick(View arg0) {
                finish();
            }
        });
    }

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

}



I read the extra data using getString/getInt/getBoolean etc... methods inside the intent returned by getIntent() method.

Example:

String powerUsageValue  = getIntent().getStringExtra("powerUsage");
powerUsage.setText(powerUsageValue);

Now the next question is how do I return back to the list. I added a button for this in the details.xml layout file. And I use finish() method to close and destroy the instance of the current activity. Afterwards the focus is returned to the MainActivity of the application.


 this.mainListBtn = (Button) findViewById(R.id.main_list_btn);
        this.mainListBtn.setOnClickListener(new OnClickListener() {
          
            @Override
            public void onClick(View arg0) {
                finish();
            }
        });



Result images:


machines list

machine details

Washing Machines app in android

I managed to create a simple application that uses ListView component and couple of TextView components to store and show data about several washing machines I collected from wikipedia.

Some of the data about machines is arbitrary so not all info is correct. This is just a practice for Android.

strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">WashingMachines</string>
    <string name="action_settings">Settings</string>
    <string name="hello_world">Hello world!</string>
    <string name="machine_type">Machine type</string>
    <string name="brand_name">Brand name</string>
    <string name="weight">Weight</string>
    <string name="maxRpm">Max RPM</string>
    <string name="washTemp">Washing temperature</string>
    <string name="hasEnergyStar">Has energy star</string>
    <string name="powerUsage">Power usage</string>
</resources>



activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    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" >

    <ListView
        android:id="@+id/scroll_view"
        android:layout_width="fill_parent"
        android:layout_height="200dp"
        android:orientation="vertical" >
    </ListView>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/machine_type" />

        <TextView
            android:id="@+id/machine_type_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/machine_type" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/brand_name" />

        <TextView
            android:id="@+id/brand_name_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/brand_name" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/weight" />

        <TextView
            android:id="@+id/weight_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/weight" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/maxRpm" />

        <TextView
            android:id="@+id/max_rpm_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/maxRpm" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/washTemp" />

        <TextView
            android:id="@+id/wash_temp_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/washTemp" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/hasEnergyStar" />

        <TextView
            android:id="@+id/has_energy_star_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/hasEnergyStar" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <TextView
            android:layout_width="140dp"
            android:layout_height="wrap_content"
            android:layout_marginRight="5dp"
            android:text="@string/powerUsage" />

        <TextView
            android:id="@+id/power_usage_view"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="@string/powerUsage" />
    </LinearLayout>

</LinearLayout>


Helper class: WashingMachine.java

package com.example.washingmachines;

public class WashingMachine {
    private String type; // top, front, hybrid
    private String brandName; // LG, Samsung, BSH, Whirlpool, Videocon, Gorenje
    private int weight; // 60kg, 80kg, 150kg, 220kg, 360kg
    private int maxRpm; // 800, 1200, 1600, 2000
    private int washTemp; // 40C, 36C
    private boolean hasEnergyStar;
    private int powerUsage; // 100kwh, 150kwh, 200kwh

    public WashingMachine() {

    }

    public WashingMachine(String type, String brandName, int weight,
            int maxRpm, int washTemp, boolean hasEnergyStar, int powerUsage) {
        super();
        this.type = type;
        this.brandName = brandName;
        this.weight = weight;
        this.maxRpm = maxRpm;
        this.washTemp = washTemp;
        this.hasEnergyStar = hasEnergyStar;
        this.powerUsage = powerUsage;
    }

    public String getType() {
        return type;
    }

    public String getBrandName() {
        return brandName;
    }

    public String getWeight() {
        return String.valueOf(weight) + " kg";
    }

    public String getMaxRpm() {
        return String.valueOf(maxRpm) + " rpm";
    }

    public String getWashTemp() {
        return String.valueOf(washTemp) + " C";
    }

    public boolean isHasEnergyStar() {
        return hasEnergyStar;
    }

    public String getPowerUsage() {
        return String.valueOf(powerUsage) + " KWh";
    }

}


MainActivity.java

package com.example.washingmachines;

import java.util.ArrayList;
import java.util.List;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class MainActivity extends Activity {
    private ListView machines = null;
    private List<WashingMachine> listOfMachines = new ArrayList<WashingMachine>();
    private ArrayAdapter<String> adapter = null;
    private List<String> machinesList = new ArrayList<String>();
    private TextView type = null;
    private TextView brandName = null;
    private TextView weight = null;
    private TextView maxRmp = null;
    private TextView washTemp = null;
    private TextView hasEnergyStar = null;
    private TextView powerUsage = null;

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

        initView();
    }

    private void initView() {

        this.machines = (ListView) findViewById(R.id.scroll_view);
       
        WashingMachine wm1 = new WashingMachine("front", "LG", 65,
                1200, 41, false, 100);
        this.listOfMachines.add(wm1);
       
        WashingMachine wm2 = new WashingMachine("top", "Samsung", 73,
                800, 60, false, 90);
        this.listOfMachines.add(wm2);
       
        WashingMachine wm3 = new WashingMachine("hybrid", "BSH", 52,
                1650, 36, true, 70);
        this.listOfMachines.add(wm3);
       
        WashingMachine wm4 = new WashingMachine("top", "Whirlpool", 105,
                1400, 56, false, 150);
        this.listOfMachines.add(wm4);
       
        WashingMachine wm5 = new WashingMachine("front", "Gorenje", 360,
                2000, 70, false, 300);
        this.listOfMachines.add(wm5);
       
        WashingMachine wm6 = new WashingMachine("hybrid", "Videocon", 300,
                2000, 85, false, 310);
        this.listOfMachines.add(wm6);
       
        this.machinesList.add(this.listOfMachines.get(0).getBrandName());
        this.machinesList.add(this.listOfMachines.get(1).getBrandName());
        this.machinesList.add(this.listOfMachines.get(2).getBrandName());
        this.machinesList.add(this.listOfMachines.get(3).getBrandName());
        this.machinesList.add(this.listOfMachines.get(4).getBrandName());
        this.machinesList.add(this.listOfMachines.get(5).getBrandName());
       
        this.type = (TextView) findViewById(R.id.machine_type_view);
        this.brandName = (TextView) findViewById(R.id.brand_name_view);
        this.weight = (TextView) findViewById(R.id.weight_view);
        this.maxRmp = (TextView) findViewById(R.id.max_rpm_view);
        this.washTemp = (TextView) findViewById(R.id.wash_temp_view);
        this.hasEnergyStar = (TextView) findViewById(R.id.has_energy_star_view);
        this.powerUsage = (TextView) findViewById(R.id.power_usage_view);
       
        this.adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1, this.machinesList);
        this.machines.setAdapter(adapter);
       
        this.machines.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                type.setText(listOfMachines.get(arg2).getType());
                brandName.setText(listOfMachines.get(arg2).getBrandName());
                weight.setText(listOfMachines.get(arg2).getWeight());
                maxRmp.setText(listOfMachines.get(arg2).getMaxRpm());
                washTemp.setText(listOfMachines.get(arg2).getWashTemp());
                hasEnergyStar.setText(listOfMachines.get(arg2).isHasEnergyStar() ? "yes" : "no");
                powerUsage.setText(listOfMachines.get(arg2).getPowerUsage());
               
            }
        });

       

    }

    @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;
    }

}


Result image

result

Friday, July 12, 2013

ScrollView practice screenshots

Here are the screenshots I got while developing

Settings
Starting up

In the middle, only first row of colors functions

Final look