Showing posts with label Android. Show all posts
Showing posts with label Android. Show all posts

Saturday, March 26, 2011

Application Ecosystem for the BlackBerry PlayBook

According to their press release, RIM has officially announced the ecosystem for applications that will run on the PlayBook tablet. Below is a quote from the release:
  • BlackBerry PlayBook to support BlackBerry Java and Android apps
  • Native C/C++ development support added, in addition to HTML5, Flash and AIR support
  • Support from leading game engines: Ideaworks Labs (AirPlay) and Unity Technologies (Unity 3)
  • BlackBerry PlayBook becomes a new market opportunity for all the developers who have already created over 25,000 BlackBerry Java apps and more than 200,000 Android apps 
The most important part for me, and something that I've been hoping for a long time, is the added support for Android. What RIM was lacking was an application ecosystem. This will not be the case anymore. And it is not only about Android in the end. Moving away from Java ME is the first step (still need it for existing applications). When you can write applications using HTML, Flash, C/C++, Java ME, and Android, you can't go wrong. There is no other ecosystem out there that provides such a diversity. 

Wednesday, November 17, 2010

Android Ginerbread adds NFC support

Listening to the conversation with Eric Schmidt at the Web 2.0 Summit 2010, I was pleasantly surprised that the new Android 2.3 (called "Gingerbread"), will add support for NFC, or Near Field Communication (I heard rumors about this in the past). There are many use cases that I can think of, the major one being using your phone for making payments. I said it in the past that the main reason I think NFC has not been adopted is because there was no major company/platform using it. Now there is.

Monday, April 12, 2010

Perfect Mobile Platform

What would make up the perfect mobile platform? What characteristics should it posses? Here are some of them, in no specific order:
  • User Interface/Experience - a rich user interface that provides a great user experience. When using the phone, everything should come naturally, with ease, and should have the WOW factor that makes you never want to leave the phone out of your hands. Doing common tasks should not take more than a few clicks. 
  • Application Ecosystem - Having many applications to chose from is not as important as having quality applications, those that satisfy a particular need, like finding a place to eat, checking your email, or playing Doom. Integrating location, social networking, and sensors is a must.
  • Internet Browsing - surf the Web from anywhere, on the go. A mobile browser should be able to render pages properly and fast, navigation should be done with ease, data should be compressed as to save bandwidth, and use the latest web technologies (HTML5, CSS, JavaScript, etc).
  • Battery Life - it better not leave me hanging after a full day of use, or in the middle of a call, or while searching for a place to eat using the GPS. 
  • Development Ecosystem - provide a rich set of APIs that can access all the features of the phone, and can provide the best user experience. Provide tools that can be used to make it easier to write apps. Publishing an application should not involve much hassle. 
  • Openness - here I refer to not only an open and free platform, but to a platform that allows any mobile technology to work on it.
  • Enterprise - features such as security, integration with email/calendar/notes/contacts servers, messaging, to name just a few. 
There is no one platform that satisfies all these needs better than any other platform. What is needed is a platform that has the user experience of iPhone and Android, the application ecosystem of iPhone (and Android very soon), the internet browsing of iPhone and Android (mostly any WebKit-based browsers), the battery life of the Blackberry, the development ecosystem of Android and iPhone, the openness of Android, and the enterprise characteristics of Blackberry. 

Will we ever have such a platform? I really doubt it. 

Thursday, April 8, 2010

Smartphone Application Downloads Forecast

ABI Research has recently published a forecast for smartphone application downloads world wide for 2009 - 2015, and which can bee seen in the chart below:


While iPhone apps are still going to be the leading source of downloads, for the year of 2010, Android is expected to have over 800 millions application downloaded, a major increase compared to 2009. Beside iPhone and Android, Blackberry and Symbian are also catching up on sales. What all this means, at least for me, is that it is a great time to be a mobile developer :)

Monday, February 8, 2010

Android XML Parsing

If you ever considered which parser to use in Android, on developer.com you can find an article that does a comparison of DOM, SAX, and XMLPullParser. Since I started working with Java ME in 2003, SAX was the XML parser of choice, since DOM consumed to much memory and was slower. Nothing changed in Android, although the pull parser is much closer in performance to SAX.

Sunday, February 7, 2010

Getting the Battery Level in Android using the SDK

Finding out the battery level using the Android SDK is not quite an easy task because this functionality is not documented, which means it can change at any point in time. Well, after reading a little more about the ACTION_BATTERY_CHANGED Intent and about the BatteryManager class, starting with API Level 5, you have all the information needed to get the status on your phone's battery. The BatteryManager class contains some String values that will give you information about the current battery level and the scale, constants such as EXTRA_LEVEL and EXTRA_SCALE. If you were to work with an API version older than 2.0 (< 5), then it becomes a little more difficult to find the right information as it is not documented in the APIs as far as I could tell.

For now, here is how you can find out:
  • Create an IntentFilter that matches the Intent.ACTION_BATTERY_CHANGED action.
  • Create a BroadcastReceiver that will be called with a broadcast intent.
  • Inside onReceive, retrieve data based on the "level" item (battery level) for version < 5, or use BatteryManager.EXTRA_LEVEL for versions >= 5.
  • Register the receiver that will be called with the broadcast intent that signals a battery change 
Here is the BatteryLevelActivity:
package edu.fau.csi.battery;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.widget.TextView;

/**
 * Used for finding the battery level of an Android-based phone.
 * 
 * @author Mihai Fonoage
 *
 */
public class BatteryLevelActivity extends Activity {
    /** Called when the activity is first created. */
    private TextView batterLevel;

    @Override
    /**
     * Called when the current activity is first created.
     */
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);
        batterLevel = (TextView) this.findViewById(R.id.batteryLevel);
        batteryLevel();
    }

    /**
     * Computes the battery level by registering a receiver to the intent triggered 
     * by a battery status/level change.
     */
    private void batteryLevel() {
        BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                context.unregisterReceiver(this);
                int rawlevel = intent.getIntExtra("level", -1);
                int scale = intent.getIntExtra("scale", -1);
                int level = -1;
                if (rawlevel >= 0 && scale > 0) {
                    level = (rawlevel * 100) / scale;
                }
                batterLevel.setText("Battery Level Remaining: " + level + "%");
            }
        };
        IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryLevelReceiver, batteryLevelFilter);
    }
    
}
The battery.xml layout file is next:

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout 
  xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical" 
  android:layout_width="fill_parent" 
  android:layout_height="fill_parent"> 
  
    <TextView         
        android:id="@+id/batteryLevel"
        android:layout_width="fill_parent" 
        android:layout_height="fill_parent" 
        android:gravity="center_vertical|center_horizontal"
        android:textSize="50dip"> 
    </TextView>
    
</LinearLayout>


As I mentioned in the beginning, if you are using Android 2.0 or higher, you can make the following changes to the batteryLevel method of the BatterLevelActivity class:
    /**
     * Computes the battery level by registering a receiver to the intent triggered 
     * by a battery status/level change.
     */
    private void batteryLevel() {
        BroadcastReceiver batteryLevelReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                context.unregisterReceiver(this);
                int rawlevel = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
                int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, -1);
                int level = -1;
                if (rawlevel >= 0 && scale > 0) {
                    level = (rawlevel * 100) / scale;
                }
                batterLevel.setText("Battery Level Remaining: " + level + "%");
            }
        };
        IntentFilter batteryLevelFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
        registerReceiver(batteryLevelReceiver, batteryLevelFilter);
    }
The code for getting the battery level was inspired from the Twisty project.

Enjoy!

Sunday, January 31, 2010

Unit and Functional Testing in Android

I don't have to tell you that testing is a fundamental part of the product development cycle, although I just did. No matter if you are developing for the desktop, web, or mobile space, you should make sure that the end software system works as required. This blog will go through two flavors of testing on the Android platform: unit and functional.

Unit tests tell the developer that the code runs correctly, while functional tests tell the developer that the code is doing what is supposed to do. To more clearly understand the difference, I will use the analogy mentioned in http://www.ibm.com/developerworks/library/j-test.html. If you think of building a system as being similar to building a house, then think of unit tests as having the building inspector at the construction's site, focusing on making sure that the internal system of the house (foundation, plumbing, etc) works correctly, while functional testing as having the homeowner visiting the house and being interested in how the house looks, if the rooms have the desired size, etc. He assumes that the internal functions of the house work properly.

In unit testing, think of a unit as being the smallest testable part of an application, such as a function/method. The goal is to isolate such parts and make sure they run correctly by being able to test them repeatably. Unit tests are written from the developer's perspective, and as a developer, we have to make sure that we understand the specification and requirements of our software system before writing unit tests. This can be achieved through use cases.

The flow of unit testing is shown below:


Android uses JUnit, and open source framework for writing and running unit tests. Some of the framework's features are:
  • Assertions for testing expected results
  • Test fixtures for sharing common data
  • Test runners for running tests
How does JUnit work? You use assert statements to assert that something is true (assertTrue(expected, actual), assertTrue(condition), etc), that something is false (assertFalse(condition), etc), that something is equal (assertEqual(expected, actual), etc). When an assert fails, the test failed for that particular case, hence your code needs to be fixed (assuming the unit test was written correctly). 

Starting with version 4.x, JUnit takes advantage of Java 5 Annotations:

  • @Test
    • Mark your test cases with the @Test annotation
  • @Before and @After
    • Used for "setup" and "tearDown" methods
    • They run before and after every test case
  • @BeforeClass and @AfterClass
    • Used for class wide "setup" and "tearDown"
    • They run one time, before and after all test cases
    • You write you initialization code (i.e. open database connection) and cleanup code (i.e. close database connection) in here
  • @Ignore
    • Used for test cases you want to ignore (i.e. on methods that are not fully implemented yet, hence are not ready to be ran)
  • Exception Handling
    • Use the "expected" parameter with the @Test annotation for test cases that expect exceptions (i.e. @Test(expected = ArithmeticException.class) ...
Let us look at a Java Example, namely a Calculator application. The class that incorporates the basic functionality of a calculator is shown below:

/**
package edu.fau.csi.junit;

/**
 * Simple class that incorporates the basic functionality of a calculator, providing methods to 
 * add, subtract, multiply, and divide to double numbers.  
 * 
 * @author Mihai Fonoage
 *
 */
public class Calculator {
    /**
     * Left operand of the operation to be performed.
     */
    private double leftOperand;
    /**
     * Right operand of the operation to be performed.
     */
    private double rightOperand;
    
    /**
     * Constructs a Calculator object by initializing the leftOperand and rightOperand 
     * with the given values.
     * 
     * @param leftOperand Left operand.
     * @param rightOperand Right operand.
     */
    public Calculator(double leftOperand, double rightOperand) {
        this.leftOperand = leftOperand;
        this.rightOperand = rightOperand;
    }
    
    /**
     * Adds the leftOperand to the rightOperand.
     * 
     * @return The sum of the two operands. 
     */
    public double add() {
        return leftOperand + rightOperand;
    }
    /**
     * Subtracts the rightOperand from the leftOperand.
     * 
     * @return The subtraction of the two operands. 
     */
    public double subtract() {
        return leftOperand - rightOperand;
    }
    /**
     * Multiply the leftOperand to the rightOperand.
     * 
     * @return The multiplication of the two operands. 
     */
    public double multiply() {
        return leftOperand * rightOperand;
    }
    /**
     * Divides the leftOperand to the rightOperand.
     * 
     * @return The division of the two operands. 
     */
    public double divide() {
        if (rightOperand == 0) {
            throw new ArithmeticException("right operand should not be zero!");
        }
        return leftOperand / rightOperand;
    }
}
I created a new source folder named test and included the following test class (by right-clicking on the project name -> New -> JUnit Test Case, choose "New JUnit 4 test", and as the class under test, search for the above Calculator class):
package edu.fau.csi.junit;

import static org.junit.Assert.assertTrue;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * JUnit Test case for the Calculator class.
 * 
 * @author Mihai Fonoage
 *
 */
public class CalculatorTest {
    
    private Calculator calculator;
    
    /**
     * Sets up the test fixture. 
     * (Called before every test case method.)
     */
    @Before
    public void setUp() {
        calculator = new Calculator(6, 4);
    }

    /**
     * Tears down the test fixture. 
     * (Called after every test case method.)
     */
    @After
    public void tearDown() {
        calculator = null;
    }

    /**
     * Test method for {@link edu.fau.csi.junit.Calculator#add()}.
     */
    @Test
    public void testAdd() {
        assertTrue(calculator.add() == 10);
    }

    /**
     * Test method for {@link edu.fau.csi.junit.Calculator#subtract()}.
     */
    @Test
    public void testSubtract() {
        assertTrue(calculator.subtract() == 2);
    }

    /**
     * Test method for {@link edu.fau.csi.junit.Calculator#multiply()}.
     */
    @Test
    public void testMultiply() {        
        assertTrue(calculator.multiply() == 24);
    }
    
    /**
     * Test method for {@link edu.fau.csi.junit.Calculator#divide()}.
     */
    @Test
    public void testDivide() {
        assertTrue(calculator.divide() == 1.5);
    }

    /**
     * Test method for {@link edu.fau.csi.junit.Calculator#divide()}.
     */
    @Test(expected = ArithmeticException.class)
    public void testDivideByZero() {
        Calculator calculator = new Calculator(6, 0);
        calculator.divide();
    }

}
To run everything, right-click on the CalculatorTest class -> Run As -> JUnit Test. All five tests should pass.

Functional tests are written from the user's perspective. They confirm that the system does what the user expected it to do, based on the functional requirements of the system, hence it focuses on the behavior that users are interested in. The tester interacts with the system to determine if the behavior is correct.

In Android, functional testing is possible through the android.test.* package(s). We are going to use the same Calculator example, adapted for Android. When you create the Calculator Android project in Eclipse, choose also co create a Test Project for it. You will end up with two project, the Calculator project and the CalculatorTest project. The layout of the Calculator project is described below:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:id="@+id/linear" 
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical">
    
    <TableLayout android:id="@+id/table" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical" 
        android:stretchColumns="1">
        <TableRow>
            <TextView android:id="@+id/leftOperand_label" 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:padding="3dip"
                android:textStyle="bold" 
                android:text="Left Operand">
            </TextView>
            <EditText android:id="@+id/leftOperand" 
                android:padding="3dip"
                android:numeric="decimal"
                android:singleLine="true"
                android:scrollHorizontally="true" 
                android:nextFocusDown="@+id/rightOperand">
            </EditText>
        </TableRow>
        <TableRow>
            <TextView android:id="@+id/rightOperand_label" 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" 
                android:padding="3dip"
                android:textStyle="bold" 
                android:text="Right Operand">
            </TextView>
            <EditText android:id="@+id/rightOperand" 
                android:padding="3dip"
                android:singleLine="true"
                android:scrollHorizontally="true"
                android:nextFocusDown="@+id/plus">
            </EditText>
        </TableRow>
    </TableLayout>
    
    <LinearLayout android:id="@+id/buttons_linear" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        
        <Button android:id="@+id/plus" 
            android:layout_width="0px"
            android:layout_height="wrap_content" 
            android:layout_weight="1"
            android:padding="6dip"
            android:text="+" 
            android:layout_gravity="center_horizontal" 
            android:nextFocusRight="@+id/minus">
        </Button>
        
        <Button android:id="@+id/minus" 
            android:layout_width="0px"
            android:layout_height="wrap_content" 
            android:layout_weight="1"
            android:padding="6dip"
            android:text="-" 
            android:layout_gravity="center_horizontal" 
            android:nextFocusRight="@+id/multiply">
        </Button>
        
        <Button android:id="@+id/multiply" 
            android:layout_width="0px"
            android:layout_height="wrap_content" 
            android:layout_weight="1"
            android:padding="6dip"
            android:text="*" 
            android:layout_gravity="center_horizontal" 
            android:nextFocusRight="@+id/divide">
        </Button>
        
        <Button android:id="@+id/divide" 
            android:layout_width="0px"
            android:layout_height="wrap_content" 
            android:layout_weight="1"
            android:padding="6dip"
            android:text="/" 
            android:layout_gravity="center_horizontal" 
            android:nextFocusRight="@+id/divide">
        </Button>
        
        <Button android:id="@+id/clear" 
            android:layout_width="0px"
            android:layout_height="wrap_content" 
            android:layout_weight="1"
            android:padding="6dip"
            android:text="C" 
            android:layout_gravity="center_horizontal" 
            android:nextFocusRight="@+id/divide">
        </Button>
        
    </LinearLayout>
    
    <TextView android:id="@+id/result" 
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:padding="20dip"
        android:textStyle="bold" 
        android:gravity="right"
        android:text="Result">
    </TextView>
    
</LinearLayout>

It is a simple layout, with two initial text fields for the left and right operand, five buttons, each for one operation, plus a clear button, and one text field that will hold the result of the calculation. As a side note, I have put the text for each of these elements inside the layout xml file to save some time; you should put them inside the strings.xml file instead.

The CalculatorActivity class is described next:

package edu.fau.csi.calculator;

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

public class CalculatorActivity extends Activity implements OnClickListener {

    private EditText leftOperand;

    private EditText rightOperand;

    private TextView result;
    
    private Calculator calculator;
    
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.calculator);
                        
        leftOperand = (EditText)findViewById(R.id.leftOperand);
        rightOperand = (EditText)findViewById(R.id.rightOperand);
        result = (TextView)findViewById(R.id.result);

        Button plus = (Button)findViewById(R.id.plus);
        plus.setOnClickListener(this);
        Button minus = (Button)findViewById(R.id.minus);
        minus.setOnClickListener(this);
        Button multiply = (Button)findViewById(R.id.multiply);
        multiply.setOnClickListener(this);
        Button divide = (Button)findViewById(R.id.divide);
        divide.setOnClickListener(this);
        Button clear = (Button)findViewById(R.id.clear);
        clear.setOnClickListener(this);

    }

    @Override
    public void onClick(View view) {
        double leftOp = Double.parseDouble(leftOperand.getText().toString());
        double rightOp = Double.parseDouble(rightOperand.getText().toString());
        calculator = new Calculator(leftOp, rightOp);
        
        if (view.getId() == R.id.plus) {
            result.setText("" + calculator.add());
        }
        else if (view.getId() == R.id.minus) {
            result.setText("" + calculator.add());
        }
        else if (view.getId() == R.id.multiply) {
            result.setText("" + calculator.multiply());
        }
        else if (view.getId() == R.id.divide) {
            result.setText("" + calculator.divide());
        }
        else if (view.getId() == R.id.clear) {
            leftOperand.setText("");
            rightOperand.setText("");
            result.setText("");
            leftOperand.requestFocus();
        }
    }
}

The Calculator class that actually does the calculations is exactly the same as the one from the Java example.

When you run this example, you will get the following screen:

The unit testing part is the same as the one mentioned in the unit testing section of this blog. You can still test your business logic without needing to interact with the application through its user interface. Actually, Calculator.java and CalculatorTest.java were just copied from the Java example to the Android without making any modifications.

Functional testing for this example involves the process of entering numbers in the two text fields, pressing one of the operations button, and checking the result to make sure it is the expected one. Instead of having the developer/user/tester do this manually, we can automate the task by sending key events through instrumentation, all from the CalculatorActivityTest class from the CalculatorTest application:
package edu.fau.csi.calculator.test;

import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;
import android.widget.TextView;
import edu.fau.csi.calculator.CalculatorActivity;


public class CalculatorActivityTest extends ActivityInstrumentationTestCase2<CalculatorActivity>{

    private TextView result;

    private CalculatorActivity calculatorInstance;

    public CalculatorActivityTest() {
        super("edu.fau.csi.calculator", CalculatorActivity.class);
    }

    /* (non-Javadoc)
     * @see android.test.ActivityInstrumentationTestCase2#setUp()
     */
    @Override
    protected void setUp() throws Exception {
        // TODO Auto-generated method stub
        super.setUp();
        calculatorInstance = (CalculatorActivity) getActivity();
        result = (TextView)calculatorInstance.findViewById(R.id.result);
    
    }

    /**
     * Test the addition operation of the CalculatorActivity
     * 
     * @throws Throwable
     */
    public void testAdd() throws Throwable {
        
        //First field value
        sendKeys( KeyEvent.KEYCODE_3 );
        sendKeys( KeyEvent.KEYCODE_PERIOD );
        sendKeys( KeyEvent.KEYCODE_5 );
        
        //Move to the second field
        sendKeys( KeyEvent.KEYCODE_DPAD_DOWN );
        sendKeys( KeyEvent.KEYCODE_2 );
        sendKeys( KeyEvent.KEYCODE_PERIOD );
        sendKeys( KeyEvent.KEYCODE_1 );

        //Move to the '+' button
        sendKeys( KeyEvent.KEYCODE_DPAD_DOWN );
        sendKeys( KeyEvent.KEYCODE_DPAD_CENTER );

        //Wait for the activity to finish all of its processing.
        getInstrumentation().waitForIdleSync();
        
        //Use assertion to make sure the value is correct
        assertTrue(result.getText().toString().equals("5.6"));
        
    } 
}

The above activity test class inherits from the ActivityInstrumentationTestCase2 that provides functional testing of a single activity, namely our CalculatorActivity. The above code only tests the add method, but similar implementations can be done for all other three calculations.

The Android manifest file for the CalculatorTest project is described next:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="edu.fau.csi.calculator.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">

    <uses-library android:name="android.test.runner" />
    </application>
    <uses-sdk android:minSdkVersion="4" />
    <instrumentation android:targetPackage="edu.fau.csi.calculator" 
        android:name="android.test.InstrumentationTestRunner" />
</manifest>

When the activity is ran for the first time, you have to create a new Android JUnit Test configuration. There are two possibilities, both shown below:

 or


When you run this, the Calculator application will start in the emulator, you will see the two text fields being populated with the values 3.5 and 2.1, the "+" button being pressed, and the result field populated with the result of the operation, namely 5.6.

I hope you find this helpful!

Tuesday, January 12, 2010

Are students prepared for working in the industry?

This should have actually been a two-part blog, first talk about the fact that there are now course on iPhone and Android programming offered at my university, and second transition to the topic mentioned in the title of the blog, namely the existing gap between what we are thought in school, and what is actually needed outside in the industry. Just by the fact that such courses are being offered, I believe that the gap is getting a little smaller. Read on to get a feel of what I think about all this.

I had my first lecture as part of the iPhone Programming class offered at FAU (similar to the course offered at Stanford and available online for free) I am excited because mobile development has been a passion of mine for some time now. I have been working with J2ME since my fourth year of college (2004), and with Android since before its official 1.0 release. Both platforms come with their advantages and shortcomings. Now, the opportunity to take part of the iPhone class could not be left unanswered, hence I enrolled for the Spring semester as part of my last class moving toward the end of my PhD.

I wanted to look into iPhone programming for some time now, but there were some impediments like not owning a Mac, and not having time for it. Well, my first problem was solved because, graciously enough, our CEECS department at FAU has created an advanced Apple Lab that comes with 10 Macs and 5 iPod Touch. My second problem got solved due to the fact that I had to take one more class, so why not make it one that is all about mobile programming. At the end of the class, I could better compare and contrast the different mobile platforms that I am familiar with.

I had some (minor) complaints about the curricula here at FAU. I felt that the courses being thought are somewhat out of touch with the need of the industry. And because most of the students end up working in the industry, better choices for courses could be offered. I have a whole list of classes that I wish would be offered here, and I am going to share this with list with you (letting me know what other classes you think would be useful):
  • Web Services (SOA more generally)
  • Software Testing (Black/White Box, Integration/Regression/Acceptance/Unit Testing, TDD)
  • Java and C# (and here maybe more on the Enterprise side with Java EE and .NET)
  • Compilers
  • Project Management (Lean, Agile (XP, Scrum), RUP, V-MODEL)
  • Functional and Logical Programming
  • Distributed Systems
  • Math for Computer Science
  • Web Developemnt (in terms of Rails, PhP, Flash, Perl, Python, GWT)
  • Software Security (Encryption, SSL/TSL, HTTPS, Cyphers, Hashes, etc)
Mobile Development class that would include Java ME, Android, and iPhone Programming, was also on the list but fortunately enough, Android and iPhone Programming are currently being taught here at FAU (I am much involved in the Android class, not as a student, but as a teaching assistant). Refactoring was also on the list, but having a whole class on this topic seems a little too much (instead it could be incorporated in any programming class available).

I recently read an article written by Bjarne Stroustrup entitled "What Should We Teach New Software Developers? Why", that expressed some of the feelings I have on this topic. Although there is still room for improvement, I do believe that we (FAU, but I am sure some universities were already on this path for some time) are going in the right direction offering courses that are useful when graduating from school.

Tuesday, December 15, 2009

Sliding Puzzle Full - First Review

I found the first review of my Android game, Sliding Puzzle Full, review made for an older version (1.0.0). I am glad James enjoyed the game. From the review:

"Sliding Puzzle Full v1.1.0 is a fun application that makes your photos take on a whole new life of their own. I liked the grid size option and the ability to choose a picture or create a new puzzle using my phones camera.


The controls are overall simple to use, the touchscreen sliding mechanism is very functional and the program offers simple fun. If you're a puzzler fan you'll love this game."

Some notes:
 - the game is available on Android Market, but it was built with version 1.6, hence some phones might not *see* it yet.
 - I will not update the slideme version of the game (which is 1.0.0). The newest version is 1.1.1 and can be found in the Android Market.

Thursday, November 12, 2009

Android Sliding Puzzle

Yesterday I released my first Android application into the Android Market. The application is a sliding puzzle game, and comes into two flavors, a free (lite) version (called "Sliding Puzzle Lite"), and a full version ("Sliding Puzzle Full") at $0.99. The lite version has only the basic features, such as 9 pre-loaded images and the ability to view the full (final) image during game play. The full version has the following features:
  • pre-loaded with 9 images
  • 4 difficulty levels (3x3, 4x4, 5x5, 6x6)
  • shuffle puzzle image
  • view final image
  • load image from SD Card
  • take a picture using the Camera and load it as a puzzle
  • displays a timer during game play 
  • displays how much percentage of the puzzle is done
  • displays the number of moves made
Below are some screen shots of the application:



I want to make some observations about the entire process.

First, the design was far from optimum in the first iteration; it was too complex for a one-screen game (one main screen, namely the puzzle screen). I started refactoring when I had to add some features and I noticed how hard it was to do just that. I ended up getting rid of some classes, methods, and instance variables all together, simplifying the design. Efficiency is crucial when developing for mobile devices. My background is in Java ME, where the restrictions are even bigger than on Android-based smartphones. For example, because I had to work with key-value pairs, instinctively I first went with a HashMap. I notice that the key-value pairs where actually pairs of integers, so I switched to using a SparseIntArray, which is more efficient that a HashMap. An even better approach would have been to use to parallel arrays of ints, but that's exactly how the SparseIntArray class is implemented, thank you for that! Overall, I tried to follow the guidelines form Designing for Performance document. Hence, the entire process was an iterative/incremental one, based on add feature <=> test feature <=> fix bugs <=> refactor (I hope the model does not look like a waterfall one because it wasn't :)). I noticed that testing and fixing bugs took the most time (and I am sure I still have bugs left unnoticed by me). I have been testing for the past month (and I've been doing all this in my spare time, being that I am working on my PhD also). Testing was still done manually (I hate that I do not use some kind of unit testing in Android). My biggest problem was that I was getting out of memory exceptions when loading bitmaps (especially when loading from SD card). I ended up using Bitmap.createScaledBitmap method to scale the bitmaps down. Furthermore, having the bitmaps displayed on the screen was initially done in a 'bulk' manner, where the screen would freeze until the first couple of images could be displayed. That's not user friendly at all; reading some blogs from smarter people, I ended up using a AsyncTask, where each image I would load, I would display on the screen, one at a time. With that, you would images being loaded on the display, similar to how the Gallery application (that comes pre-loaded on the phone) works.

Second, nothing beats testing on a real device. Emulators do come close, but having a device made quite a difference. For example, on some G1 phones, the camera software has a known bug, namely that the camera preview does not work in portrait mode. This issue is of course non-existent in the emulator.

I keep telling fellow students that I work with (or teach to), that nothing beats writing applications. Sure, you can read books (which of course you have to do), run examples, but if you do not start coding, you will never get to the next level as a programmer.

There are other lessons I have learned, and maybe I will post them in a later post.

Overall, I am looking forward to adding new features to the full version of the game (such as speech recognition, integration with Facebook, and many more), and also developing the next game from the list of ideas that I have.

I hope you enjoy the sliding puzzle, at least as much as I enjoyed developing it!

Wednesday, October 21, 2009

Current and upcoming Android Phones

WiseAndroid has gathered a list of 50+ Android Phones that are currently on the market or will become available in the near future. TechCrunch provides images for (some of) the phones. Thank you for the effort!

Monday, September 28, 2009

Displaying images from SD card in Android

Below you will find a Android example of how to access and display images that are stored on your SD card.

I wrote part 2 for this article, where images are loaded in the background using an asynchronous task. It is an improvement over this article, but I strongly suggest trying this one first to fully appreciate the differences between the two approaches.

The main idea is to make use of the MediaStore class, which is a Media provider that contains data for all available media on both internal and external storage devices (such as an SD card). An adapter is used as a bridge between the data and the view.

The activity is shown below:

package blog.android.sdcard;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.AdapterView.OnItemClickListener;

/**
 * Displays images from an SD card.
 */
public class SDCardImagesActivity extends Activity {

    /**
     * Cursor used to access the results from querying for images on the SD card.
     */
    private Cursor cursor;
    /*
     * Column index for the Thumbnails Image IDs.
     */
    private int columnIndex;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sdcard);

        // Set up an array of the Thumbnail Image ID column we want
        String[] projection = {MediaStore.Images.Thumbnails._ID};
        // Create the cursor pointing to the SDCard
        cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
                projection, // Which columns to return
                null,       // Return all rows
                null,
                MediaStore.Images.Thumbnails.IMAGE_ID);
        // Get the column index of the Thumbnails Image ID
        columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);

        GridView sdcardImages = (GridView) findViewById(R.id.sdcard);
        sdcardImages.setAdapter(new ImageAdapter(this));

        // Set up a click listener
        sdcardImages.setOnItemClickListener(new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position, long id) {
                // Get the data location of the image
                String[] projection = {MediaStore.Images.Media.DATA};
                cursor = managedQuery( MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, // Which columns to return
                        null,       // Return all rows
                        null,
                        null);
                columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToPosition(position);
                // Get image filename
                String imagePath = cursor.getString(columnIndex);
                // Use this path to do further processing, i.e. full screen display
            }
        });
    }

    /**
     * Adapter for our image files.
     */
    private class ImageAdapter extends BaseAdapter {

        private Context context;

        public ImageAdapter(Context localContext) {
            context = localContext;
        }

        public int getCount() {
            return cursor.getCount();
        }
        public Object getItem(int position) {
            return position;
        }
        public long getItemId(int position) {
            return position;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
            ImageView picturesView;
            if (convertView == null) {
                picturesView = new ImageView(context);
                // Move cursor to current position
                cursor.moveToPosition(position);
                // Get the current value for the requested column
                int imageID = cursor.getInt(columnIndex);
                // Set the content of the image based on the provided URI
                picturesView.setImageURI(Uri.withAppendedPath(
                        MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, "" + imageID));
                picturesView.setScaleType(ImageView.ScaleType.FIT_CENTER);
                picturesView.setPadding(8, 8, 8, 8);
                picturesView.setLayoutParams(new GridView.LayoutParams(100, 100));
            }
            else {
                picturesView = (ImageView)convertView;
            }
            return picturesView;
        }
    }
}
The layout of the main activity is shown below:

<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/sdcard"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:padding="10dp"
    android:verticalSpacing="10dp"
    android:horizontalSpacing="10dp"
    android:numColumns="auto_fit"
    android:columnWidth="90dp"
    android:stretchMode="columnWidth"
    android:gravity="center"
/>

In order for this to work, you need to emulate an SD card.

Enjoy!

UPDATE (October 19, 2009): In order to be bale to view thumbnails images from the SD Card, Android needs to create them first, hence you should start the Gallery application that comes preinstalled, and open the sdcard folder which will automatically create thumbnails for the images stored on your sdcard. This is a current shortcoming of the SDK that will be fixed in future releases (http://groups.google.com/group/android-developers/browse_thread/thread/3f01b284e2537312/fa9487d19db4907e).

UPDATE (October 07, 2009): For some reason, if you use
MediaStore.Images.Thumbnails.IMAGE_ID
like in the previous version of the above code, the images are not always displayed on the screen. Changing to
MediaStore.Images.Thumbnails._ID
seems to solve the problem. I will look more into why and get back to you.
Furthermore, some images have the wrong path attached to them.  I changed the creation of the cursor object from
cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null,       // Return all rows
null,
null);
to
cursor = managedQuery( MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI,
projection, // Which columns to return
null,       // Return all rows
null,
MediaStore.Images.Thumbnails.IMAGE_ID);

Thursday, July 9, 2009

Scripting in Android

Damon Kohler released last month the Android Scripting Environment (ASE), which enables running Python scripts in Android. Access to location and sensors, activities and intents, phone calls and text messaging, are just a few examples of the APIs available to scripts.

A more detailed article on this topic can be found on the Motorola developer blog.

Thursday, April 16, 2009

Android and Symbian on Netbooks

Corresponding to a report by In-Stat, HP is pushing Android into Netbooks. From the Information Alert:

"This solution bypasses the huge memory, storage, and graphics requirements associated with Windows and lowers hardware cost, as well as the software cost. It also addresses the changes in the market. Over the past decade, we've seen two megatrends in electronics – mobility and the Internet. As content and applications migrate to the Internet, these trends will change to mobile Internet and Internet ubiquity. Adopting Android or another open source OS with a custom UI and good browser technology addresses these changes in many specific applications and usage models."

I do agree with the article, and I believe that Android will have a bigger impact on non-smartphone devices (such as Netbooks) than it will have on smartphones.

Symbian is not behind on all this. According to this article, the S60 5th Edition runs on a "off the shelf Intel Atom based motherboard", which means directly on the x86 hardware. The difference is that Symbian runs on x86, while Android runs on ARM.

Wednesday, April 15, 2009

Android 1.5 (Cupcake) Highlights

Android 1.5 introduces new and exciting features. Here are some that I find important:
  • Accelerometer-based application rotations
  • Faster Camera start-up and image capture
  • Much faster acquisition of GPS location (powered by SUPL AGPS)
  • Smoother page scrolling in Browser
  • Video recording and playback
  • Bluetooth: stereo bluetooth support (A2DP and AVCRP profiles), auto-pairing, improved handsfree experience
  • Browser: copy 'n paste in browser, search within a page
  • Framework for easier background/UI thread interaction
  • Raw audio recording and playback APIs
  • Support for using speech recognition libraries via Intent
  • LocationManager - Applications can get location change updates via Intent
  • Broadcast Intent for app update install succeeded - for smoother app upgrade experience
For a complete list of features, visit the android developers web page.

Thursday, March 19, 2009

Android 1.1 and iPhone 3.0

If you want a feature-by-feature comparison of Android and iPhone, read the Android Versus iPhone 3.0 article by lifehacker. Do remember that Android is only in its 1.1 release, while iPhone has seen its 3.0 version. Even though iPhone has more available features, let us not forget that Android is open source.

Sunday, March 15, 2009

Smartphone sales numbers

According to a Gartner report, smartphones sales grow by almost 14% compared to 2007. What is encouraging are the news regarding Android-based smartphones:

"Sales of Linux-based smartphones were up by 19 per cent year-over-year, mainly through Android-based smartphones being available through T-Mobile during the fourth quarter of 2008."

I expect this number to grow with upcoming Android-based smartphone models.

Tuesday, February 10, 2009

Android Presentation

Today I did a presentation to a group of students on Android, basically an overview of the platform. If you are interested, you can find the presentation here. Any comments are welcomed!

Tuesday, January 13, 2009

Related concepts from Android and Java ME

I was thinking about the main components that provide the building blocks for your Android application, and on how they relate to similar concepts from the Java Micro Edition (Java ME) platform:

Activity. Activities in Android are the presentation layer for the application you are building. For each screen you have, their will be a matching Activity. Similar to this concept, in Java ME you have Forms (and more general maybe Screens). An Activity uses Views to build the user interface; similarly, a Form uses different items such as text fields, data fields, choice groups, etc. Generally speaking, in Java ME, on a Screen (or on a displayable), you can place a Canvas, an Alert, a List, a TextBox, and finally a Form. All these elements are used to build the graphical user interface for displaying information to the user and interacting with him by responding to the user actions.

Services. Services are those components that run in the background, and which do not interact with the user. They can update your data sources and Activities, and trigger specific notifications. I tried to think of a similar component in Java ME, but could not come with one. The only concepts I could think of was Threads and Timers (a way for threads to schedule tasks for execution in a background thread). The concept of Threads exists separately in Android also, hence such a comparison is not quite precise. Until background MIDlets are available with the upcoming of MIDP 3, I guess we do not have any other options.

Content Providers. They encapsulate data and provide it to your application, therefor acting as interfaces to the application databases. Sharing data across applications is achieved also by means of Content Providers. Such a concept is related to the RecordStores in Java ME, and more general, to the Record Management System (RMS - the persistent storage mechanism in Java ME).

Intents. Intents are a way of specifying what intentions you have in terms of a specific action being performed. Intents are mostly used for launching Activities. A similar concept in Java ME is described in the Broadcast Receivers section.

Broadcast Receivers. These components listen for broadcast Intents that match some defined filter criteria, and can automatically start your application as a response to an intent. Looking closely at the Intents and Broadcast Receivers components, for me, PushRegistry comes into mind. A PushRegistry is used to request a wakeup call from the implementation. What is important to understand about PushRegistry is the fact that they have a lifetime beyond that of a MIDlet. It is part of the MIDlet management software that runs on the device. When your MIDlet registers (at runtime or at install time) for push notifications, the device is obligated to listen incoming network connections and start your MIDlet if the appropriate connection has been made.

Notifications. Notifications let you signal the user by alerting him of an incoming event, and without using a separate Activity to achieve that. For example, you are monitoring the weather, and you want to be notified when a hurricane warning is in effect for your area (common in South Florida where I leave). This can be accomplished by adding Notifications to your weather monitoring system. In Java ME, one similarity would be the use of Alerts that inform the user about different events.

In later posts, I will describe more similarities between the two platforms at different levels. Stay tuned!

Monday, December 15, 2008

Most Popular Android Applications for November 2008

FastCompany has published a post regarding the most popular Android Applications for November 2008:

SOURCE: fastcompany.com