Friday 30 September 2011

Android: Programmatically receiving SMS messags

As I`m sure you already know or at least suspect by now, it`s possible to programmatically "intercept" incoming short messages like SMS and/or MMS. All you need is the right permissions and a few lines of code.
Preparing the manifest file
The first thing we're going to do is to give the app permission to receive SMS messages. Just add the uses permission android.permission.RECEIVE_SMS using the manifest editor or the xml tag
 
<uses-permission android:name="android.permission.RECEIVE_SMS"> 

directly into the manifest file.

Now that we can receive SMS messages, we need to register an Intent Broadcast Rreceiver that will be called whenever a message arrives. More information about broadcast receivers can be found here.

Before we continue with the changes to the manifest file, let's talk about implementing our broadcast receiver class. Fortunately the framework already has a handy base class for that so we just need to extend it and override the proper method.

In our example we'll use the following class:

class MySMSReceiver extends BroadcastReceiver{
  @Override
  public void onReceiver(Context context, Intent intent){
    //do something with the message received
  }
}

To register a broadcast receiver, in the application section of your manifest file add

<receiver android:name=".MySMSReceiver "> 
    <intent-filter> 
            <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
    </intent-filter> 
</receiver> 

The most important thing to notice in the xml snippet above is android:name=".MySMSReceiver ". the name attribute sets the class to be instantiated when the broadcast for the intent is received. The "." is not a type, we're just telling android to find the class MySMSReceiver in the current package.

Also note that the receiver has an intent filter tag, meaning that only that type of intent will be passed to the intent receiver. Android will make sure the receiver code runs even if your app is not running.

Now let's see how to get the content of the the received message.

The SMS messages in Android use the PDU format (Protocol Description Unit) meaning that the content (sender, body, etc) is available in text mode albeit encoded. But fear not, the API can easily decode PDU data.

The message received by the broadcast receiver is available in the extras of the intent under the tag "pdus". Let's change our receiver to decode the first PDU of the message received

  class MySMSReceiver extends BroadcastReceiver{
  @Override
  public void onReceiver(Context context, Intent intent){
    Object[] pdus=(Object[])intent.getExtras().get("pdus");
    SmsMessage shortMessage=SmsMessage.createFromPdu((byte[]) pdus[0]);

    Log.d("SMSReceiver","SMS message sender: "+
       shortMessage.getOriginatingAddress());
    Log.d("SMSReceiver","SMS message text: "+
       shortMessage.getDisplayMessageBody());
  }
}

And there we have it! You can find more about the fields in the message in the SDK documentation. Remember that SMS messages can be relayed through email-to-sms relays, meaning that the sender can often be an email address and not a phone number.

Wait, did you notice that pdus is an array? That's because the SMS protocol allows for 160 characters long messages only. If the message is longer than that, several PDU objects will be created.
So to assemble a message broken down into several PDUs, just iterate the array:

...
    Object[] pdus=(Object[])intent.getExtras().get("pdus");
    String sender="";
    StringBuilder text=new StringBuilder();
    // get sender from first PDU
    SmsMessage shortMessage=SmsMessage.createFromPdu((byte[]) pdus[0]);
    sender=shortMessage.getOriginatingAddress();
    for(int i=0;i<pdus.length;i++){
      shortMessage=SmsMessage.createFromPdu((byte[]) pdus[i]);
      text.append(shortMessage.getDisplayMessageBody());
    } 
...

Next post I will talk about sending SMS messages, which is much easier  ;)

---
Programming tricks and tips for android developers

32 (or so) big mobile fails

Whatever Happened to the iPad Rivals of 2010?
The (mostly) sad fates of 32 early answers to Apple's tablet.

Full story here.

RIM still betting on Playbook

I had to post it here. Mostly because I think it's funny.
Rumors suggesting that the BlackBerry PlayBook is being discontinued are pure fiction," RIM spokeswoman Marisa Conway said in an emailed statement. "RIM remains highly committed to the tablet market and the future of QNX in its platform."
Source here

Thursday 29 September 2011

Android: Localizing your Android app - Part 1

Nowadays one could think that everybody speaks English so your English-only app is probably good enough.
Well, localizing software is not just about translating, there are several cultural and behavioral aspects you have to consider.
The Android framework brilliantly provides us with several resources to make our apps shine anywhere in the world.

As I said, depending on the app, we need more than just translating to make it localized. A financial app definitely wants to use the correct currency and number formatting of the targeted country/culture.

That said, today we will start small: learning how to write our apps so it can be easily translated to other languages.


1) Using string resources
One  of the first things we learn (or should have learned) in computer programming is to never leave hardcoded strings (text) lying around in the code. That, by the way, is a code smell and it's why we make constants.

However when we're talking translation of text to another languages, the simple use of constants is not useful anymore.
We need to put ALL strings/text that will be DISPLAYED to the user in a separate place. The Android solution for that is the use of string resources.

By default, a file called strings.xml is created by Eclipse under res/values/ and it looks somewhat like this:

<xml version="1.0" encoding="utf-8">
<resources>
    <string name="app_title">Test app</string>
</resources> 


Eclipse has a nice editor to help you edit and add more strings but you'll find that editing the XML directly is more efficient. So to add a new string (anything you want to localize), just add a new string node setting the attribute name to something you know to be unique.

The name is how we refer to that string in our app. For instance, if my title of the application is displayed in a TextView sitting on the activity's layout like

<TextView android:text="Test app"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/> 


the "localizable" version of the TextView would look like

<TextView android:text="@string/app_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/> 


by referring to the content using @string we are telling the framework to find the string resource where name=app_title and use it as text for the TextView.

Tips when working with string resources:
  1. use them even if you're not planning to translate your app;
  2. the default file is called strings.xml but what really matters is the xml tags so you can name your string resource files the way you find more appropriate;
  3. if your app has several activities and/or fragments, it's probably a good idea to create multiple string resource files;
  4. name (remember name="..." attribute?) the strings as if you're naming variables: you'll need to refer to them quite often.
  5. you can use xml tags in your string resource files and the framework will automatically interpreted them for you. For example if you put Test app as the content of the string, android will display the text in bold letters.

2) Creating string resources for each of the languages
Now to the interesting part: the translated resources.
I wrote somewhere above that the string resources reside under res/values. Well, the name of directory values is that one that tells android what language the string resources are. The name of the directory is prefixed with a dash "-" plus the locale code for the language in question.

 
So a directory called values-fr will have content in French, values-es in Spanish and so on. Creating another strings.xml under res/values-es with the content



<xml version="1.0" encoding="utf-8">
<resources>
    <string name="app_title">AplicaciĆ³n de Test</string>
</resources>



will make your app automatically display the content in Spanish for devices using Spanish locale.
notice that the name "app_title" is the same and must be the same for any locale.

The directory res/values contains the default string resources for any locale and it's always a good practice to have defaults.

3) Testing your app

Testing the translated version of your app is simple, just change the locale of the phone/emulator and reboot it (at least I always had to reboot for the change to take effect).
To change the locale in the emulator, click on the apps button and you should see an app called Custom Locales. Select an existing one or create your own.
Reboot the emulator and done!

Next post I will talk about using resource strings in the code and how to localize other types of resources.



---
Programming tricks and tips for android developers

2011 ig Nobel Prize is out

A little off topic but interesting nonetheless.

From The 2011 Ig® Nobel Prize Ceremony:
The 2011 Ig Nobel Prize Ceremony Thursday, September 29, 7:30 pm. Sanders Theater, Harvard University, Cambridge, Massachusetts The 21st First Annual Ig Nobel Prize Ceremony will introduce ten new Ig Nobel Prize winners. The winners will travel to the ceremony, at their own expense, from several continents. The Prizes will be handed to them by a group of genuine, genuinely bemused Nobel Laureates, assisted by a large number of assorted Ig personnel, all before a perpetually standing-room only audience.
Past winners list

Wednesday 28 September 2011

Kindle Fire: E-Ink goodness is no more

I think even the dead know by now that Amazon has announced their own Android tab: called Kindle Fire, AKA iPad Killer (or Galaxy Tab Killer, Xoom Killer, *Killer).

Smart move but the media here in North America have no idea what they're talking about when they say this device could cause Apple et al problems. Not that I'm defending any of the already established tablets, it's just that nobody is looking at the hardware specs.

Granted not much is known about what's inside Fire's case but it's clearly not a challenge for, let's say, an iPad  - the new Kindle doesn't even have a camera.

Ok, most Kindle users probably will not care for the hardware because the price is exceptionally good when compared to other tablets. Some Samsung's tabs have similar hardware and are much more expensive.

I have a traditional Kindle reader and in my opinion it's an awesome reader only because of the e-Ink screen. Kindle Fire sports a LCD IPS display, which is not so great for reading.
Will Kindle Fire potential buyers realize that before rushing to the e-store? Maybe the new IPS display is better than I think it is and in this case I apologize Amazon.

My point here is that there's no point. Tabs and Phones are all about the apps and in Amazon's case: books. Android market+Amazon store have more than enough stuff to keep you busy.
If you want an e-book reader and a tablet, you will probably buy the Fire.

It's not out until November but Amazon is accepting orders (last time I checked).

Samsung shipping Galaxy Tab 8.9 in October in US


Samsung Galaxy Tab 8.9 Pre-Order Goes Live, Galaxy Players 4.0 And 5.0 To Follow Checkout the full news

Tuesday 27 September 2011

Android: Creating a transparent/translucent applications (activity)

Recent posts:
Android: Localizing your Android app - Part 1
Android: displaying widgets in a grid-like layout
Android: displaying widgets in a grid-like layout - Part 2, The TableLayout
Android: Getting all and maximum megapixels supported by the camera
Android: Taking pictures without a preview window
Android: Sending emails without user intervention

I get this question all the time and the solution is very simple.
Just set the theme of the app to one of the following:

  • Theme.Translucent
  • Theme.Translucent.NoTitleBar
  • Theme.Translucent.NoTitleBar.Fullscreen

To do that, just edit the manifest file and add, in the application section, android:theme="@android:style/Theme.Translucent" (or any of the above)

for instance
<application android:icon="@drawable/icon" android:label="@string/app_name" android:theme="@android:style/Theme.Translucent">
...

This will make your app look like this


Theme.Translucent.NoTitleBar and Theme.Translucent.NoTitleBar.Fullscreen  produce


I think Theme.Translucent.NoTitleBar.Fullscreen was supposed to hide the system's status bar but what happens is that the status bar is never hidden. When using any of the *Fullscreen themes, the app window just extends on top of the status bar.

Have fun.


---
Programming tricks and tips for android developers

Monday 26 September 2011

Apple reportedly cuts iPad orders by 25% for Q4 – or production shifts to Brazil

Holly crap! Could it really be? Full story here

Sunday 25 September 2011

Is project Kal-El really the future of mobile gaming?

Don't know, but so far it's looking very cool, check out the video.



More here

Friday 23 September 2011

Android: displaying widgets in a grid-like layout - Part 2, The TableLayout

Continuing the layout series, I'll talk about how to display content in a grid style using TableLayout.

To make use of the TableLayout we need 2 elements: TableLayout and TableRow. One TableLayout element can have multiple TableRows. Each TableRow represents a row (I'm so obvious) and everything we put inside a TableRow creates 1 column.

For example

<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content">
  <TableRow android:layout_width="wrap_content" android:layout_height="wrap_content" >
    <TextView android:background="#555555" android:text="Cras in eros nunc" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
    <TextView android:background="#999999" android:text="non viverra justo" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
  </TableRow>
</TableLayout>


this layout snipped will produce this

Each text view is one column. I again changed the background colour just to make it easier to differentiate each column.

and when I add 2 more TextViews like this


<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content">
  <TableRow android:layout_width="wrap_content" android:layout_height="wrap_content" >
    <TextView android:background="#555555" android:text="Cras in eros nunc" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
    <TextView android:background="#999999" android:text="non viverra justo" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> 


    <TextView android:background="#555555" android:text="1" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
    <TextView android:background="#999999" android:text="01/01/2011" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
  </TableRow>
</TableLayout>



I get this

2 more columns, which is pretty cool, except for the fact they look like a single string of text.

To make the columns use all available width, we just need to the table which columns we want to "stretch" changing the attribute android:stretchColumns. This attribute takes a list of columns indices (zero-based), separated by commas if you want to stretch more than one.


For instance, I want to give more space for the last two columns (2 and 3)

<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="2,3">
  <TableRow android:layout_width="wrap_content" android:layout_height="wrap_content" >
    <TextView android:background="#555555" android:text="Cras in eros nunc" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
    <TextView android:background="#999999" android:text="non viverra justo" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView> 


    <TextView android:background="#555555" android:text="1" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
    <TextView android:background="#999999" android:text="01/01/2011" android:layout_width="wrap_content" android:layout_height="wrap_content"></TextView>
  </TableRow>
</TableLayout>


This makes my table look like this



Much better but still not very good. Let's tell the table to stretch all columns. Just put a * as the value for stretchColumns

<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="*">

and bang, there you have it


We can also do the opposite, instead of giving more space for columns, we can shrink them using android:shrinkColumns. Let's say that 3rd column ( index 2), the one with the number "1" is using too much space. Changing the TableLayout definition to 


<TableLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:stretchColumns="0,1,3" android:shrinkColumns="2">


produces


To hide (collapse) a column, use android:collapseColumns again passing the indices of the columns you want to get rid of.

And if you want more lines in your table, just keep adding TableRows. You can put virtually anything inside a TableRow just remember that the column with the largest width wins!

Naturally you'll have to find what fits your app best. Remember to test with different screen densities and orientations. Be aware of TABS!!


---
Programming tricks and tips for android developers

Wednesday 21 September 2011

Android: displaying widgets in a grid-like layout

(UPDATE)
Now that Ice Cream sandwich is here, we also can user the new GridLayout. I'll write about it as soon as I have time.

It sounds simple but I get this question all the time: How do I make TextView, EditText, Buttons, and such to be evenly distributed in a grid like layout?

There are many ways to do that (I think) but the simplest one is using a standard LinearLayout with android:orientation="horizontal", adjusting the property layout_weight of each widget inside the layout.

If we create a layout like this


<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Cras in eros nunc"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="non viverra justo"/>
</LinearLayout>


we'll get this

which one could say doesn't look very good.
But if we add android:layout_weight="1" to each of the text views, like 

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Cras in eros nunc"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="non viverra justo"/>
</LinearLayout>


the 2 text views will use respectively 50% of the width of the parent, looking like this

 android:layout_weight basically set how much of the usable area a widget can use. It accepts floating numbers so we can do things like this:

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.1"
android:background="#ff0000"
android:text="Cras in eros nunc"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="0.9"
android:background="#0000ff"
android:text="non viverra justo"/>
</LinearLayout>




and get this

note that I changed the background colour just to make the difference more visible.

As I mentioned, the weight is applied to the available area inside the parent and in the examples above, the parent has android:layout_width="fill_parent". If we change it to android:layout_width="wrap_content" this happens.


So be aware of your surroundings!

Next post I'll talk about TableLayouts and TableRows.

Have a good one!

Tuesday 20 September 2011

Android: Getting all and maximum megapixels supported by the camera (s)

In your camera app you often need to give the user options for picture size, supported by the camera that is. Or even if it's not an options, you might want to set the picture size to the maximum possible.

To do that you first need to get a list of supported image sizes. The method
Camera.Parameters.getSupportedPictureSizes
( documented here) can help us with this task. The returned value is a list of picure sizes which (among other things) contains the width and height of the supported picture size. With some simple math we can get the number of Megapixels supported by the camera.

So less talk more code


public List getAllSupportedMegapixelsByCamera(int cameraID){
  List mpList=new ArrayList();
  Camera myCamera=Camera.open(cameraID) ; // use Camera.open() for the default back facing camera or if you're supporting an older sdk version.
  
  // make sure the camera is not in use or something.
  if(myCamera!=null){
    Camera.Parameters allParams=myCamera.getParameters();
    for(Camera.Size pictureSize: allParams.getSupportedPictureSizes ()){
      int sizeInMegapixel=Math.round((pictureSize.width*pictureSize.height)/1000000);
      mpList.add(sizeInMegapixel);
    }
  }

  return mpList;
}
The returned list will contain values like 2 5 7 ... meaning that the camera supports pictures of size 2 5 and 7 megapixels.

Two not-so-popular and really cool Android games

Since I started talking about apps, I tried 2 puzzles this weekend that are the kind of thing developers like. The first one is Isaac Newton's Gravity. Several physics puzzles that can be quite challenging and make you spend hours trying to crack them.

The other one is Minesweeper 3D. Not much to say about it, except that it's a great revamping of a classic.

Monday 19 September 2011

Top (free) financial apps for Android

A little off topic (or not) but I'd like to share my excitement when I found that most major banks (and Canadian top 5 banks) have free financial apps for their customers. It's probably obvious and one could argue that the app is not actually free since you need a bank account. But since even King Kong has a bank account these days, it's probably worth checking out the apps before expending too much money on a paid one that does the same thing.

Sunday 18 September 2011

Android: Taking pictures without a preview window

Why on earth one would want to take a picture with your Android phone without knowing what's going to be capture? Well, apps have their reasons, like the SOS app NoDistress.


Taking pictures programmatically is easy: do the same thing you'd do but set a dummy surface view to the camera.

Example

public void takePictureNoPreview(Context context){
  // open back facing camera by default
  Camera myCamera=Camera.open();

  if(myCamera!=null){
    try{
      //set camera parameters if you want to
      //...

      // here, the unused surface view and holder
      SurfaceView dummy=new SurfaceView(context)
      myCamera.setPreviewDisplay(dummy.getHolder());    
      myCamera.startPreview(); 
      
      myCamera.takePicture(null, null, getJpegCallback()):
      
    }finally{
      myCamera.close();
    }      

  }else{
    //booo, failed!
  }


  private PictureCallback getJpegCallback(){
    PictureCallback jpeg=new PictureCallback() {   
      @Override
      public void onPictureTaken(byte[] data, Camera camera) {
        FileOutputStream fos;
        try {
          fos = new FileOutputStream("test.jpeg");
          fos.write(data);
          fos.close();
        }  catch (IOException e) {
          //do something about it
        }
      }
    };
  }
}


---
Programming tricks and tips for android developers

Android: Sending emails without user intervention (Using Javax Mail API).

Android API doesn't have support for any email protocols but the good news is that there's a javax implementation (a very good one by the way) here.
Download here these files:

  • mail.jar
  • additionnal.jar
  • activation.jar

and add them to your Android project as external jars. To do that in Eclipse, open the project properties (right click on the project name and click properties) and select Java Build Path. Click on the tab Libraries and them Add External JARs. Select the downloaded files and that's it.


Here's a simple example to programmatically send emails using SMTP with authentication but NO SSL/TLS:

public class MySMTPSendMail extends javax.mail.Authenticator {

  private String mUserName;
  private String mPassword;
  private String mHostName;

  public void sendEmailTo(String user, String password, String hostname, String recipient, String body)  throws AddressException, MessagingException{

    mUserName=user;
    mPassword=password;
    mHostName=hostname;

    Properties props = getProperties();


    // this object will handle the authentication
    Session session=Session.getInstance(props,this);
    MimeMessage emailMessage=new MimeMessage(session);
    BodyPart msgBody=new MimeBodyPart();
    MimeMultipart bodyMultipart=new MimeMultipart();


    emailMessage.setFrom(new InternetAddress(mUserName));
    emailMessage.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipient));  

    emailMessage.setSubject(body);    
    msgBody.setText(body);   
    bodyMultipart.addBodyPart(msgBody);
    emailMessage.setContent(bodyMultipart);

    Transport.send(emailMessage);
  }

  private Properties getProperties(){
    Properties props = new Properties(); 
   
    props.put("mail.smtp.host", mHostName);   
    props.put("mail.smtp.auth", "true");           
    // default SMTP port
    props.put("mail.smtp.port", "25"); 
  }

  @Override 
  public PasswordAuthentication getPasswordAuthentication() { 
    return new PasswordAuthentication(mUserName, mPassword); 
  } 
}

To send emails using SSL encryption, just change the method getProperties() to something like

  private Properties getProperties(){
    Properties props = new Properties(); 
   
    props.put("mail.smtp.host", mHostName);   
    props.put("mail.smtp.auth", "true");           
    // default SMTP over SSL port
    props.put("mail.smtp.port", "465"); 
    props.put("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); 
    props.put("mail.smtp.socketFactory.fallback", "false"); 
  }


To send emails using TLS encryption (e.g, live.com) change the method getProperties() to

  private Properties getProperties(){
    Properties props = new Properties(); 
   
    props.put("mail.smtp.host", mHostName);   
    props.put("mail.smtp.auth", "true");           
    // default SMTP over SSL port
    props.put("mail.smtp.port", "465"); 
    props.put("mail.smtp.socketFactory.port", "465");
    props.put("mail.smtp.starttls.enable", "true");   
  }

Good luck!! ;)

Saturday 17 September 2011

Android: Modifying UI elements from inside a Thread

Just don't do what the title says :)

Modifying anything that extends the View class from inside a thread is bound to fail. This is very common in any widget/UI SDK and Google brilliantly provided us with a few options.

The first one - that I will not talk about much - is Activity.runOnUIThread. Just create a class extending Runnable and call this method. If the current thread is not the UI thread, the runnable will be posted to the main thread event queue and processed later. So DON'T abuse this call or you may overwhelm the main thread.

A much more flexible and interesting approach is to use AsyncTask, which allows you to neatly organize code that must run asynchronously an in the main (UI) thread.
Again you'll have to create your on class extending AsyncTaks with 3 generic types: Parameters, Progress and Result.

The most common use of your class would be:
  1. override the method doInBackground implementing all that stuff that has to happen in background;
  2. override onPostExecute implementing the code that MUST run in the UI thread
  3. Call execute(Params...) to start the task;

For instance:


public class CalculateMD5 extends AsyncThread<String, int, String>{
  @Override
  protected String doInBackground(String... filename){
    // running in background
    // calculate md5 of files
    ...
  }

  @Override
  protected onPostExecute(String result){
    // running in the UI thread
    myTextView.setText("MD5: "+result);
  }
}

 

if you wan to display the progress to the user, call publishProgress from doInBackground and override the method onProgressUpdated, which also runs in the UI thread.

public class CalculateMD5 extends AsyncThread<String, int, String>{
  @Override
  protected String doInBackground(String... filename){
    // running in background
    // calculate md5 of files
    publishProgress(number_of_bytes_processed/total_bytes);
    ...
  }

  @Override
  protected onPostExecute(String result){
    // running in the UI thread
    myTextView.setText("MD5: "+result);
  }

  @Override
  protected void onProgressUpdate(int... progress){
    //% processed ...
  }
}

 
and last but nor least, if you need to prepare things before the background processing starts, override onPreExecute, another method that runs in the UI thread.

You must start the task from the UI thread.
You should always check if the task is not cancelled in your doInBackground method. Use isCancelled for that.

Simple isn't it? So recaping what runs where:
  • UI Thread
    • onPreExecute
    • onProgressUpdate
    • onPostExecute
    • onCancelled
  • Backgroun thread
    • doInBackground
---
Programming tricks and tips for android developers