Thursday, November 19, 2009

On Chrome OS

Last night (IST) Google presented the Chrome OS details and opened the source code. I did some early twits looking inside the source code. Found the bits of clutter, debian, moblin down under there. My point of view was traditional. What a long time Linux user sees in a brand new OS - Window Manager, Package manager, RPC mechanism, etc. This was as soon as @mattcutts had posted that chromium source was out and before the actual presentation even started. When I however saw the presentation (vicariously that is - through the glasses of many tweeters and Gizmodo's live report), I found that, what I was looking for in the OS was totally irrelevant ...

If you haven't seen the ChromeOS presentation videos, do check them out.

I won't go over all the features here, but this is what I liked the most

1. Security. Automatic patching of OS everytime it boots. I liked the thinking behind this model.
The basic application security model was developed 20 years ago. Right now, the application runs with “your” privileges, so if you can modify something, the app you’re running can do it also. So a rogue app can damage your data or leak your data. It also forces users to make hard decisions about whether or not you trust the application. “These are decisions that are hard for normal users to make decisions about.”

- as reported by Jason Chen of Gizmodo

2. Local file system. It is treated merely as a cache before the settings are pushed up into the cloud. It is completely encrypted, so in case of device loss, there is no fear of data theft.

3. Only SSDs. By the time first ChromeOS devices will ship, SSDs will be commonplace. Besides it seems the cloud will make local storage less important than the network connection. Also only supporting this very limited storage hardware, eases the driver support. Good move.

4. Firmware. When I first studied about the LinuxBIOS project, I came to realize how wasteful the booting process is. The BIOS initializes the hardware, reads the kernel from the storage device, starts the kernel and the kernel initializes the hardware again. The root of this setup is in the way our computers evolved and not much in the form of technical challenge. ChromeOS is going to support only specific firmware. Their boot process is tuned so that no redundant initalization steps are required, thus improving the boot time greatly. As I said, this is not a new invention. Projects like LinuxBIOS had the same implementation, but only on the hacked up devices in their labs. Now however, with Google putting its weight behind this new family of ChromeOS devices, it seems that we will be freed from the wasteful boot up process after all.

Putting things in perspective... I have liked Apple's devices. Simple, elegant, functional, work out of the box. Why is that so? Why don't they freeze once in a while or give BSOD like Windows. Why don't they have configuration problems like Linux, after all at the core they have a community developed open source kernel just like linux. The reason lies in Apple completely owning the entire OS stack. They only design, implement, test, debug and deliver for a specific set of hardware. That's why they can concentrate all their design and engineering skills into making the best computing devices in the market.

I think Google is going to do the same with ChromeOS. Except in their case, the kernel will be Linux and Google won't be "owning" the stack, but will be tightly controlling it. Most of the stack will be open source, for anyone to look at and adapt to their devices if they want to. They will however have complete control on what goes and doesn't go in the official ChromeOS, just like Android (and that is entirely fair and necessary IMO, no matter what FOSS extremists say). On top of this (and most importantly), they will have a unique cloud based computing vision in building these next generation devices.

I like the way Google uses its power in completely reinventing certain fields with their products. ChromeOS is yet another example and worthy of cheer at that.

Android AsyncTask template

Any meaningful GUI application needs to employ multiple threads, otherwise it is very likely to lock while doing any I/O operations - leaving bad impression on the user. Same is true for Android apps. In fact, android framework prompts user to close the app if it doesn't respond in 10 seconds or so. So it's absolutely essential to perform any task - that has even a remote possibility of taking a bit longer - in a background thread.

Fortunately Android framework has some useful constructs built into the framework that make our job relatively easy while doing multithreaded GUI programming. android.os.AsyncTask is one of them.

The basic steps to make your app multithreaded using AsyncTask are as follows:
1. Identify the code segment that you want to execute in background thread. (for e.g. code that does network i/o, bulk file transfer on local disk, etc)

2. Model it as an AsyncTask object.
(Subclass the AsyncTask object and put your code segment in the doInBackground(...) method)

3. Figure out what parameters you have to pass to the task, the result that the task should return and how to handle the exception in case something goes wrong.

This is pretty simple, but the third step gets bit complicated as your app grows and there are multiple asynchronous tasks that you want to code in.

When I was faced with this problem during the development of CuTewit, I stumbled through some steps. After a while I managed to create a template for modelling with AsyncTasks. In my second app - ReaderScope - the same template worked very nicely. ReaderScope has over 50 different tasks that are run on background thread at one time or another. The template I use, has made it pretty easy to add new AsyncTasks.

In this post, I want to share that template with you. I have written a small example app that demonstrates the use of the template. Download source tarball and apk to try it yourself.

Here is the source code of AppTask.java (the derivative of AsyncTask) for discussion.

package com.altcanvas.asynctemplate;

import android.os.AsyncTask;

public class AppTask extends AsyncTask<AppTask.Payload, Object, AppTask.Payload>

{
    public static final String TAG = "AppTask";

    public static final int APPTASK_1 = 1001;
    public static final int APPTASK_2 = 1002;

    /*
     * Runs on GUI thread
     */
    protected void onPreExecute() {
    }

    /*
     * Runs on GUI thread
     */
    public void onPostExecute(AppTask.Payload payload)
    {
        switch(payload.taskType) {

        case APPTASK_1:
            AsyncTemplateActivity app =
                (AsyncTemplateActivity) payload.data[0];

            if(payload.result != null) {

                // Present the result on success

                int answer = ((Integer) payload.result).intValue();
                app.taskStatus.setText("Success: answer = "+answer);

            } else {
                // Report the exception on failure

                String msg = (payload.exception !=null) ?
                                payload.exception.toString() : "";
                app.taskStatus.setText("Failure: error ="+msg);
            }

            break;

        case APPTASK_2:
            break;
        }
    }

    /*
     * Runs on GUI thread
     */
    public void onProgressUpdate(Object... value)

    {
        int type = ((Integer) value[0]).intValue();

        switch(type) {

        case APPTASK_1:
            AsyncTemplateActivity app = (AsyncTemplateActivity) value[1];
            int progress = ((Integer) value[2]).intValue();
            app.progressBar.setProgress(progress);
            break;

        case APPTASK_2:
            break;
        }

    }

    /*
     * Runs on background thread
     */
    public AppTask.Payload doInBackground(AppTask.Payload... params)

    {
        AppTask.Payload payload = params[0];

        try {
            switch(payload.taskType) {
            case APPTASK_1:

                // extract the parameters of the task from payload

                AsyncTemplateActivity app =
                    (AsyncTemplateActivity) payload.data[0];
                int numSteps = ((Integer) payload.data[1]).intValue();

                if(numSteps < 0) throw new AppException("Invalid input");

                // perform the task

                int progress = 0;
                for(; progress < numSteps; progress++) {
                    try {
                        // pretend to work for 1 second

                        Thread.currentThread().sleep(1000);
                    } catch(InterruptedException ie) {
                        break;
                    }
                    publishProgress(new Object[] {
                            new Integer(APPTASK_1), app, progress});
                }

                publishProgress(new Object[] {
                        new Integer(APPTASK_1), app, progress}); 
                // Return result of the task
                payload.result = new Integer(42);
                break;

            case APPTASK_2:
                break;
            }
        } catch(AppException ape) {
            payload.exception = ape;
            payload.result = null;
        }

        return payload;
    }

    public static class Payload
    {
        public int taskType;
        public Object[] data;
        public Object result;
        public Exception exception;

        public Payload(int taskType, Object[] data) {
            this.taskType = taskType;
            this.data = data;
        }
    }
}

code syntax highlighting by GVIM,

Let's go over different aspects of this code.

What is Payload?
To simplify the management of passing parameters and carrying result/exception back, we create a special object called Payload. Payload carries four entities - the type of the AsyncTask (int taskType), parameters to the task (Object[] data), result of the task (Object result), exception that took place during the task (Exception exception).

Note the signatures of doInBackground and onPostExecute. The same payload object is passed around.

How do you start a new task?

new AppTask().execute(new AppTask.Payload(
    AppTask.APPTASK_1,
    new Object[] { AsyncTemplateActivity.this,
    new Integer(numSteps) })); 
   
[You can find it in AsyncTemplateActivity.java in the sample app]

How do you define a new async task?
You don't have to create another AsyncTask derivative object. Just define a new taskType, e.g. APPTASK_2 in AppTask.java. Create a switch case for that taskType in each of 'doInBackground', 'onPostExecute', 'onProgressUpdate'. Depending upon the nature of the tasks, the contents of payload.data will vary. Since this data is passed as generic Object[], you can pass around any types of objects that suite the task's needs. On the other hand, you have to be careful to not type cast them to wrong classes.
[We loose Java's static type checking by defining params and result as generic 'Object's. But it saves us from repetitively defining similar AsyncTask derivatives]

How is the progress of the task updated?
When you call publishProgress(...), it results in a call to onProgressUpdate(...) which is running in the GUI thread. Here, you can manipulate any widget like progress bar to indicate the task progress.

...

This may not be the only way to code AsyncTask, but it certainly has worked for me - not just for one, but for two sizeable projects. Before this, it used to be pretty cumbersome to define a new task.

You can download the source code and use it in your app if you like.

Any comments and suggestions are welcome.


Flattr this



Ads:


Thursday, November 12, 2009

ReaderScope v1.3.3 - offline podcasts

ReaderScope primarily started as an Android app to access Google Reader from the phone. Over time however, various features were added as they proved complimentary to the act of news reading - like sharing the news with friends (Twitter, SMS, Email); bookmarking it (Del.icio.us); reading what others think about it (Digg, Reddit, FriendFeed); support for rich forms of news, i.e. podcasts and youtube videos, etc.

This release improves one of those fringe features, that of Podcasts. ReaderScope supports scheduled download of news items for reading offline. However that wasn't supported for podcasts yet. This release tries to address that problem a bit.

Now as you click on a podcast beacon, you will be asked whether you want to play the podcast right away or just download it for later listening.


If you choose to download, it will start downloading in the background (with progress in the notification). When the download is complete, you can listen to it by clicking on the notification. You can do this when you are offline too.

Furthermore, you can choose to download multiple podcasts simultaneously. They will download in parallel and will be accessible via their independent notifications.

You can listen to them one by one after they are downloaded. When the podcast ends or if you choose to stop it; the local downloaded file is automatically deleted freeing the storage it occupies.

How do you like it? Let me know.

Also in this release there are some bug fixes. There was a glitch in the Google News and Twitter news features. If you were to sync your feeds with "Thorough" option, the feeds under Google News and Social Channels would disappear. This release fixes that problem.

That's it for now. Upgrade to v1.3.3 and let me know if there's any problem.

Cheers!

Friday, November 06, 2009

ReaderScope v1.3.2 - Social Channels

Few months back I realized that all the stories I read in my slashdot or ars-technica feeds seemed kinda ... stale. Why? Because most of the interesting ones I had already read - through links posted by the people I follow on Twitter. It is now a cliché to say that Twitter is the fastest medium of spreading news. Consequently, it's the news channel that delivers the latest news. Moreover, it's the news that you care about most; because it is coming from the people you have chosen to follow.

So how can a modern news reader be complete without incorporating this real time news channel.

In v1.3.2, ReaderScope introduces Social Channels.


You will see a third tab "Social" when you start the upgraded ReaderScope. You will find a preset Twitter subscription there. When you tap on it, you will be asked to login to Twitter (if you haven't already). Once it gets Twitter credentials, you can tap it again and it will download you twitter timeline. It won't show you all the twits (that is for dedicated twitter clients). Instead, it will go through all the twits and will pick the ones that have embedded links in them. ReaderScope will fetch the stories/pictures/videos pointed to by those links and when it's done, they will be presented to you as news items (with the original twits as yellow subtext).



How do you like that?

You can also schedule the Twitter subscription for periodic download.

You will see lot of other improvements in this version too, especially the item list (it now has author and timestamp, right in the list). The news fetched from Google News channels, looks fresh (unread) now; instead of dull in color. The unread counts have been fixed too.

On Podcast front: the ones that take too long "Preparing" (because of long time in buffering over slow network) can now be stopped.

So download the upgrade and enjoy.

And yes... in case you haven't noticed yet, ReaderScope is now accepting donations. ReaderScope is available FREE of cost for everyone to use. Some users who are avid news readers, will see great value in it. While others may not. So it's up to you to decide what's ReaderScope worth to you. If you can express it in terms of $$, you will help towards further development of ReaderScope. You can find the donate button on this page

... better yet, let me paste that button right here. :)






Thanks for all your support. More features are coming to ReaderScope. Show your support and help it improve.

Cheers!