Wednesday, July 25, 2012

Tutorial on Android Voice recognition


You may have heard about the "Google Now project" where you give the voice command and Android fetches result for you. It recognizes your voice and converts it into the text or takes the appropriate action. Have you ever thought how is it done? If your answer is voice recognition API, then you are absolutly right. Recently while playing with Android voice recognition APIs, I found some interesting stuffs. APIs are really easy to use with application. Given below is a small tutorial on voice/speech recognition API. The final application will look similar to that of application shown below. The application may not work on the Android Emulator because it doesn't support voice recognition. But the same can work on the phone.


Android jelly bean voice recognition application prompt

Project Information: Meta-data about the project.

Platform Version : Android API Level 15.
IDE : Eclipse Helios Service Release 2
Emulator : Android 4.1(API 16)

Prerequisite: Preliminary knowledge of Android application framework, and Intent.

Voice recognition feature can be achieved by RecognizerIntent. Create an Intent of type RecognizerIntent and pass the extra parameters and start activity for the result. It basically starts the recognizer prompt customized by your extra parameters. Internally voice recognition communicates with the server and gets the results. So you must provide the internet access permission for the application. Android Jelly Bean(API level 16) doesn't  require internet connection to perform voice recognition.  Once the voice recognition is done, recognizer returns value in  onActivityResult() method parameters.
First create project by Eclipse > File> New Project>Android Application Project. The following dialog box will appear. Fill the required field, i.e Application Name, Project Name and Package. Now press the next button.


Once the dialog box appears, select the BlankActivity and click the next button.


Fill the Activity Name and Layout file name in the dialog box shown below and hit the finish button.
Android voice recognition project setup



This process will setup the basic project files. Now we are going to add four buttons in the activity_voice_recognition.xml file.  You can modify the layout file using either Graphical Layout editor or xml editor. The content of the file is shown below. As you may notice that we have attached speak() method with button in onClick tag. When the button gets clicked, the speak() method will get executed. We will define speak() in the main activity.


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <EditText
        android:id="@+id/etTextHint"
        android:gravity="top"
        android:inputType="textMultiLine"
        android:lines="1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:text="@string/etSearchHint"/>
    
    <Button
        android:id="@+id/btSpeak"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="speak"
        android:padding="@dimen/padding_medium"
        android:text="@string/btSpeak"
        tools:context=".VoiceRecognitionActivity" />

    <Spinner
        android:id="@+id/sNoOfMatches"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/saNoOfMatches"
        android:prompt="@string/sNoOfMatches"/>
    
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/tvTextMatches"
        android:textStyle="bold" />

    <ListView
        android:id="@+id/lvTextMatches"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
You may have noticed that the String constants are being accessed from the resource. Now add the string constants in string.xml. This file should look similar to the one shown below.
<resources>
    <string name="app_name">VoiceRecognitionExample</string>
    <string name="btSpeak">Speak</string>
    <string name="menu_settings">Settings</string>
    <string name="title_activity_voice_recognition">Voice Recognition</string>
    <string name="tvTextMatches">Text Matches</string>
    <string name="sNoOfMatches">No of Matches</string>
    <string name="etSearchHint">Speech hint here</string>
    <string-array name="saNoOfMatches">
        <item>1</item>
        <item>2</item>
        <item>3</item>
        <item>4</item>
        <item>5</item>
        <item>6</item>
        <item>7</item>
        <item>8</item>
        <item>9</item>
        <item>10</item>
    </string-array>
</resources> 
Now let's define the Activity class. This activity class, with the help of checkVoiceRecognition() method, will first check whether the Voice recognition is available or not. If voice recognition feature is not available, then toast a message and disable the button. Speak() method is defined here which gets called once the speak button is pressed. In this method we are creating RecognizerIntent and passing the extra parameters. The code below has embedded comments which makes it easy to understand.


package com.rakesh.voicerecognitionexample;

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

import android.app.Activity;
import android.app.SearchManager;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;

public class VoiceRecognitionActivity extends Activity {
 private static final int VOICE_RECOGNITION_REQUEST_CODE = 1001;

 private EditText metTextHint;
 private ListView mlvTextMatches;
 private Spinner msTextMatches;
 private Button mbtSpeak;

 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_voice_recognition);
  metTextHint = (EditText) findViewById(R.id.etTextHint);
  mlvTextMatches = (ListView) findViewById(R.id.lvTextMatches);
  msTextMatches = (Spinner) findViewById(R.id.sNoOfMatches);
  mbtSpeak = (Button) findViewById(R.id.btSpeak);
  checkVoiceRecognition()
 }

 public void checkVoiceRecognition() {
  // Check if voice recognition is present
  PackageManager pm = getPackageManager();
  List activities = pm.queryIntentActivities(new Intent(
    RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0);
  if (activities.size() == 0) {
   mbtSpeak.setEnabled(false);
   mbtSpeak.setText("Voice recognizer not present")
   Toast.makeText(this, "Voice recognizer not present",
     Toast.LENGTH_SHORT).show();
  }
 }

 public void speak(View view) {
  Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

  // Specify the calling package to identify your application
  intent.putExtra(RecognizerIntent.EXTRA_CALLING_PACKAGE, getClass()
    .getPackage().getName());

  // Display an hint to the user about what he should say.
  intent.putExtra(RecognizerIntent.EXTRA_PROMPT, metTextHint.getText()
    .toString());

  // Given an hint to the recognizer about what the user is going to say
  //There are two form of language model available
  //1.LANGUAGE_MODEL_WEB_SEARCH : For short phrases
  //2.LANGUAGE_MODEL_FREE_FORM  : If not sure about the words or phrases and its domain.
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
    RecognizerIntent.LANGUAGE_MODEL_WEB_SEARCH);

  // If number of Matches is not selected then return show toast message
  if (msTextMatches.getSelectedItemPosition() == AdapterView.INVALID_POSITION) {
   Toast.makeText(this, "Please select No. of Matches from spinner",
     Toast.LENGTH_SHORT).show();
   return;
  }

  int noOfMatches = Integer.parseInt(msTextMatches.getSelectedItem()
    .toString());
  // Specify how many results you want to receive. The results will be
  // sorted where the first result is the one with higher confidence.
  intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, noOfMatches);
  //Start the Voice recognizer activity for the result.
  startActivityForResult(intent, VOICE_RECOGNITION_REQUEST_CODE);
 }

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (requestCode == VOICE_RECOGNITION_REQUEST_CODE)

   //If Voice recognition is successful then it returns RESULT_OK
   if(resultCode == RESULT_OK) {

    ArrayList textMatchList = data
    .getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);

    if (!textMatchList.isEmpty()) {
     // If first Match contains the 'search' word
     // Then start web search.
     if (textMatchList.get(0).contains("search")) {

        String searchQuery = textMatchList.get(0);
                                           searchQuery = searchQuery.replace("search","");
        Intent search = new Intent(Intent.ACTION_WEB_SEARCH);
        search.putExtra(SearchManager.QUERY, searchQuery);
        startActivity(search);
     } else {
         // populate the Matches
         mlvTextMatches
      .setAdapter(new ArrayAdapter(this,
        android.R.layout.simple_list_item_1,
        textMatchList));
     }

    }
   //Result code for various error. 
   }else if(resultCode == RecognizerIntent.RESULT_AUDIO_ERROR){
    showToastMessage("Audio Error");
   }else if(resultCode == RecognizerIntent.RESULT_CLIENT_ERROR){
    showToastMessage("Client Error");
   }else if(resultCode == RecognizerIntent.RESULT_NETWORK_ERROR){
    showToastMessage("Network Error");
   }else if(resultCode == RecognizerIntent.RESULT_NO_MATCH){
    showToastMessage("No Match");
   }else if(resultCode == RecognizerIntent.RESULT_SERVER_ERROR){
    showToastMessage("Server Error");
   }
  super.onActivityResult(requestCode, resultCode, data);
 }
 /**
 * Helper method to show the toast message
 **/
 void showToastMessage(String message){
  Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
 }
}

Here is the Android manifest file. You can see that  INTERNET permission has been provided to the application because of the voice recognizer's need to send the query to the server and get the result.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rakesh.voicerecognitionexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="15" />
    <!-- Permissions -->
 <uses-permission android:name="android.permission.INTERNET" />
 
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
       
        <activity
            android:name=".VoiceRecognitionActivity"
            android:label="@string/title_activity_voice_recognition" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Once you are done with coding then connect the phone with your system and hit the run button on Eclipse IDE. Eclipse will install and launch the application. You will see the following activities on your device screen.
Web search using voice recognition
In the next tutorial, we will learn how to use the new voice recognition API introduced in Android Jelly Bean(API level 16) along with the examples.
If you are interested in the source code, then you can get it from github.

Other links:


Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Tuesday, July 24, 2012

Where is the Android Jelly Bean Source code?

I have been looking for Android Jelly bean source code since its release. I found a lot of blogs on the source code release, but they hardly provided any pointer to get the Android 4.1 source code. Although Google has announced the release of the source code, on checking the Android website for source code, it still shows Android 4.0(Icecream sandwich). Seems that Google hasn't updated the web-page accordingly.  If you are wondering why am I interested so much in the source code then please go through this post "Android source code browsing". While I started my quest for Android source code, I found couple of resources from where you can explore/download the Android 4.1 source code.

Android source code browsing resources:

  • Android googlesource.com web site : This is the official website of Android source code. However they have not updated the download instructions. You can use same instructions given on the page except the "repo init" command. Use command below for "repo init".
    repo init -u https://android.googlesource.com/platform/manifest -b android-4.1.1_r3
    
  • Android xref :  This website has recently indexed the Android 4.1 source code. It has been developed to make Android source code browsing easier. It doesn't have as much functionanlities as that of grepcode.com, but it is still a good website(At the time of writing, grepcode has not indexed the Android 4.1 source code.).
  • Git hub repo: This is the github site which has the latest Android 4.1 source code. If you are interested in only downloading the source code then this is really a good one. If you are looking for code browsing, then this site is not as good as that of Android xref or grepcode.

Similar post:


Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Sunday, July 22, 2012

Monkey test on Android application.

You may be wondering about the test name or thinking that it may be a misnomer. Well, this is not a misnomer. It is a kind of stress test done on an application.

Monkey Test:

Monkey test is a kind of Unit test that runs with no specific test case in mind. Test cases are randomly selected and executed. For example, giving random string to text-field or clicking some random buttons of the application. These kind of test cases check the stability of the application. Monkey test is a kind of black box test.
In my career, I have seen such kind of tests in telecommunication domain (handset manufacturer). In such test cases, the tester can do any sort of random things on the phone and check whether the phone application can handle such scenario or not. In real world no one is going to educate people about how to use the phone. They use the phone in N number of ways and expect it to work under all circumstances. 

Android Monkey test:

If you are an Android application developer and want to do Monkey test on the application, then you can use Android Monkey command line application. It generates a stream of random pseudo user events such as button click, touch, gesture etc. This application can be run on your device or emulator. Monkey test can be used to do stress test on the application.

Perquisite: Android SDK should be present and Android Debug Bridget(ADB) should be accessible. 

During the test if an exception occurs or the application crashes, then Monkey will stop the execution or you can even instruct Monkey to continue the test after exception. It also provides certain debugging configurations where you can configure monkey to get the test execution log.
You may be wondering if Monkey randomly generates the events,  then is it possible to create the same test scenario? I would say yes, Monkey takes care of that. If you give the same seed value (-s option) then Monkey creates same sequence of events. This feature enables you to reproduce the same scenario and allows to take the log and analayze the issue.

Running Monkey test on Android application:

#basic command format:
$ adb shell monkey [options] <event-count>
#To get command argument information, run the following command.
$ adb shell monkey --help
#The command below exercises monkey test on given package(your.package.name here)
# It enables the verbosity and fires 500 random events
$ adb shell monkey -p your.package.name -v 500 
#If you want to increase the verbosity, then increase the number of v like shown below.
#The default verbosity is Level 0 which shows minimum information, 
#i.e startup notification, test completion, and final results
$ adb shell monkey -p your.package.name -vvv 500 
#you can also target activity with certain category
#e.g android.intent.category.LAUNCHER
$ adb shell moneky -p your.package.name -c android.intent.category.LAUNCHER -v 500
#The throttle option enables you to keep delay between events.
#The command below fires events after 3 seconds and generates 50 events.
$adb shell monkey -p your.package.name -v -throttle 3000 50 

you can know more about Application Exerciser Monkey here

Monkey, sometimes, creates problem with adb server. If you notice that adb server is not behaving properly, then you may have to restart the server. Use the following command to do so.
adb kill-server
adb start-server 


Related topics:
Android tutorials
How to do stuff in Android?

Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest." 
By : Confucius

Friday, July 20, 2012

How to check the Android build version during runtime?

Suppose you are writing an application and want to make sure that min sdk version is supported by the application,  well in such a scenario you would probably specify it in the Android manifest using the following tag.
   <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="11" /> 
True, but what if you are using feature which is not essential for application and is available on certain Android API level or above? Definitely, you will enable or disable the component based on the availability. For example, the application uses the ActionBar available on Android API level 11 or above and you need to determine the Android version during runtime to enable/disable the application component using the ActionBar. The answer to all this is Build class . Build class helps to determine the Android version during run-time. Example code is shown below.

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
            ActionBar actionBar = getActionBar();
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

Related topics:
Android tutorials
How to do stuff in Android?

Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Wednesday, July 18, 2012

Permalink: New feature introduced in blogger.

If you are an active blogger then you must be aware of the SEO and ways to customize your blog to get the greater traffic. Earlier Blogger had introduced the "Search Description" feature to provide more control  on indexing of blog, posts, and images so they appear correctly in search results. Now they have introduced one more feature called "Permalink" where you have more control on customizing the blog url. Earlier the url used to get generated automatically by the Blogger.com based on the post heading. But now the blog writer can customize the URL providing  more control on search preferences which can eventually provide more information on the post to the viewer while scanning  the search result. For example if I don't customize URL post for this blog it would be
"http://errorbuster.blogspot.com/2012/07/permalink-new-feature-introduce-in.html". But when I  use this feature to customize the blog link, it is published as 
"http://errorbuster.blogspot.com/2012/07/cutomURL.html". You may have noticed that customURL.html  has been customized. 

If you are interested to use this feature then click permalink present on the Post Setting pan.


Once you click the permalink, it provides you with two options Automatic and custom URL. On selecting Automatic URL, the blogger generates URL based on the post heading. On the other hand on selecting  Custom URL, you can provide your own URL. If the given URL already exists then Blogger suggests other free  available URL.

At present,  limited characters are allowed on URL. These are a-z, A-Z, 0-1. The only special characters available are underscore, dash, and period.




Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Tuesday, July 17, 2012

Tutorial on new Android Jelly Bean notification

You may have heard about Android Jelly Bean (API level 16). Google has improved a lot of features and introduced new features. One of them is the notification. Now they have made the notification more versatile by introducing media rich notification. Google has come up with three special style of notification which are mentioned below. Even developer can write his own customized notification style using remote view.The old Notification class constructor has been deprecated and a brand new and enhanced version of Notification has been introduced.

Notification Type:

  • Basic Notification - Shows simple and short notification with icon.
  • Big Picture Notification - Shows visual content such as bitmap.
  • Big Text Notification - Shows multiline Textview object.
  • Inbox Style Notification - Shows any kind of list, e.g messages, headline etc. 

Old syntax requires us to create an object of notification but now Android uses builder patter to create the notification object. Notification.Builder class has been introduced to make this task easier. This class returns the builder object which is configurable according to your requirements. The helper classes have been introduced like Notification.BigPictureStyle, Notification.BigTextStyle, and Notification.InboxStyle. These classes are re-builder classes which take object created by Notification.Builder class and  modify the behavior like so.

Project Information: Meta-data about the project.

Platform Version : Android API Level 16.
IDE : Eclipse Helios Service Release 2
Emulator : Android 4.1(API 16)

Prerequisite: Preliminary knowledge of Android application framework, and Intent.

First create project by Eclipse > File> New Project>Android Application Project. The following dialog box will appear. Fill the required field, i.e Application Name, Project Name and Package Name. Don't forget to select the Build SDK version (for this tutorial Google API 16 has been selected). Now press the next button.

 Once the dialog box appears, select the BlankActivity and click the next button.



 Fill the Activity Name and Layout file name for the dialog box shown below and hit the finish button.


This process will setup the basic project files. Now we are going to add four buttons in the activity_main.xml file.  You can modify the layout file using either Graphical Layout editor or xml editor. The content of the file should look like this.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:gravity="center_horizontal">

    <Button
        android:id="@+id/btBasicNotification"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|center_vertical"
        android:onClick="sendBasicNotification"
        android:text="@string/btBasicNotification" 
        android:background="@drawable/button_background"
        android:textColor="#000000"
        />
    <Button
        android:id="@+id/btBigTextNotification"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|center_vertical"
        android:onClick="sendBigTextStyleNotification"
        android:text="@string/btBigTextNotification" 
        android:background="@drawable/button_background"
        android:textColor="#000000"
        />
   <Button
        android:id="@+id/btBigPictureNotification"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|center_vertical"
        android:onClick="sendBigPictureStyleNotification"
        android:text="@string/btBigPictureNotification"
        android:background="@drawable/button_background"
        android:textColor="#000000" />
   <Button
        android:id="@+id/btInboxStyleNotification"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal|center_vertical"
        android:onClick="sendInboxStyleNotification"
        android:text="@string/btInboxStyleNotification"
        android:background="@drawable/button_background"
        android:textColor="#000000"/>
</LinearLayout>

You may have noticed that onClick methods are associated with respective buttons. If you don't know how to define and use the background file for view then ignore the android:background field. Now we are going to define the methods sendBasicNotification, sendBigTextStyleNotification, sendBigPictureStyleNotification and sendInboxStyleNotification. As the method name suggests, it sends that particular kind of notification. In each method we are creating Notification.Builder object, and customizing the object. Here builder pattern has been used to customize the object. Once the customization is done,  call build() method to get the notification object. In this new notification system, at most three actions can be associated to a notification, which are displayed below the notification content.  This can be achieved by calling addAction() method on the builder object. The same number of icons you will see on the notification as you will notice for sendBigPictureStyleNotifcation() method. Notification priority can also be set by calling setPriority() method as shown in sendBigTextStyleNotification() method. In the code given below, intent has been used to invoke the HandleNotificationActivity.

package com.example.jellybeannotificationexample;

import android.app.Activity;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;

public class NotificationMainActivity extends Activity {

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

 @Override
 public boolean onCreateOptionsMenu(Menu menu) {
  getMenuInflater().inflate(R.menu.activity_main, menu);
  return true;
 }

 public void sendBasicNotification(View view) {
  Notification notification = new Notification.Builder(this)
    .setContentTitle("Basic Notification")
    .setContentText("Basic Notification, used earlier")
    .setSmallIcon(R.drawable.ic_launcher_share).build();
  notification.flags |= Notification.FLAG_AUTO_CANCEL;
  NotificationManager notificationManager = getNotificationManager();
  notificationManager.notify(0, notification);
 }

 public void sendBigTextStyleNotification(View view) {
  String msgText = "Jeally Bean Notification example!! "
    + "where you will see three different kind of notification. "
    + "you can even put the very long string here.";

  NotificationManager notificationManager = getNotificationManager();
  PendingIntent pi = getPendingIntent();
  Builder builder = new Notification.Builder(this);
  builder.setContentTitle("Big text Notofication")
    .setContentText("Big text Notification")
    .setSmallIcon(R.drawable.ic_launcher)
    .setAutoCancel(true);
    .setPriority(Notification.PRIORITY_HIGH)
    .addAction(R.drawable.ic_launcher_web, "show activity", pi);
  Notification notification = new Notification.BigTextStyle(builder)
    .bigText(msgText).build();
 
  notificationManager.notify(0, notification);
 }

 public void sendBigPictureStyleNotification(View view) {
  PendingIntent pi = getPendingIntent();
  Builder builder = new Notification.Builder(this);
  builder.setContentTitle("BP notification")
    // Notification title
    .setContentText("BigPicutre notification")
    // you can put subject line.
    .setSmallIcon(R.drawable.ic_launcher)
    // Set your notification icon here.
    .addAction(R.drawable.ic_launcher_web, "show activity", pi)
    .addAction(
      R.drawable.ic_launcher_share,
      "Share",
      PendingIntent.getActivity(getApplicationContext(), 0,
        getIntent(), 0, null));

  // Now create the Big picture notification.
  Notification notification = new Notification.BigPictureStyle(builder)
    .bigPicture(
      BitmapFactory.decodeResource(getResources(),
        R.drawable.big_picture)).build();
  // Put the auto cancel notification flag
  notification.flags |= Notification.FLAG_AUTO_CANCEL;
  NotificationManager notificationManager = getNotificationManager();
  notificationManager.notify(0, notification);
 }

 public void sendInboxStyleNotification(View view) {
  PendingIntent pi = getPendingIntent();
  Builder builder = new Notification.Builder(this)
    .setContentTitle("IS Notification")
    .setContentText("Inbox Style notification!!")
    .setSmallIcon(R.drawable.ic_launcher)
    .addAction(R.drawable.ic_launcher_web, "show activity", pi);

  Notification notification = new Notification.InboxStyle(builder)
    .addLine("First message").addLine("Second message")
    .addLine("Thrid message").addLine("Fourth Message")
    .setSummaryText("+2 more").build();
  // Put the auto cancel notification flag
  notification.flags |= Notification.FLAG_AUTO_CANCEL;
  NotificationManager notificationManager = getNotificationManager();
  notificationManager.notify(0, notification);
 }

 public PendingIntent getPendingIntent() {
  return PendingIntent.getActivity(this, 0, new Intent(this,
    HandleNotificationActivity.class), 0);
 }

 public NotificationManager getNotificationManager() {
  return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
 }
}


We have defined basic HandleNotificationActivity which just shows a simple message when intent is fired for this activity. The content of the file is as following.
package com.example.jellybeannotificationexample;

import android.app.Activity;
import android.os.Bundle;

public class HandleNotificationActivity extends Activity {

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

The corresponding layout file(handle_notification_activity.xml) is given below
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
     android:gravity="center_horizontal|center_vertical" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/tvHandleNotification"
        android:textSize="20dp"
        android:textStyle="bold|italic" />

</LinearLayout>

Now you have to define the Android manifiest file. HandleNotificationActivity should be included in the manifest file and then put the intent filter for this activity.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.jellybeannotificationexample"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="16"
        android:targetSdkVersion="16" />

    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name">
        <activity
            android:name=".NotificationMainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".HandleNotificationActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


Once you are done with the coding, just execute it. You will see the application as shown in the picture below. On clicking the button you will see the corresponding notification on the upper part of the screen. If you drag the notification down then you can see the entire message and corresponding icon. The  pictures below are the notification when they were dragged down.
jelly bean media rich notification application
Application
Andriod Jelly bean (API 16) Basic notification
Basic notification
Andriod 4.1 (API 16) Big Text style notification
Big Text Style
Andriod 4.1 Jelly bean (API 16) Big picture style notification
Big Picture Style
Andriod 4.1 Jelly bean (API 16) Inbox style notification
Inbox Style

If you are interested to know more about source code, you can find it over here.

Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Saturday, July 14, 2012

Prettify: A syntax highlighter for blogger


Recently I started writing technical blogs and soon I realized the need to use the syntax highlighter in order to make code look pretty on the blogs. Initially I stumbled upon SyntaxHighlighter and used it for a while. Later I noticed that the code sections didn't appear on the RSS feeds and on Mobile version of blogspot. It gave a clear indication that I may end up loosing some groups of audience using RSS feed or mobile version. It was very much evident from audience stats provided by blogger.com. The moment I realized this, I started looking for the fix or different solution which can work in the given scenarios. I couldn't find the fix for SyntaxHighilighter but I found that google android blog uses some syntax highlighter which works for RSS feed and even for the mobile version of blog. On investigating further with the help of Firebug, I found that PrettyPrint is used to highlight the syntax. 
PrettyPrint is present on googlecode.com as well. At the same time I discovered some facts about PrettyPrint which influenced me to use it. These are listed below.

Comparison:

PrettyPrint SyntaxHighlighter
It's light and requires only two files (prettyprint.js and prettyPrint.css)  You need to include different js files for different syntaxes.
Minified js file is provided Minified js is not provided.
Takes less bandwidth because it's minified and only two files need to be downloaded by browser. Takes more bandwidth because it's not minified and if you have included more files then it takes longer to download.
You can see the code on RSS feed and mobile blog but the code is not highlighted. You can't see the code section and you may loose audience using RSS feed and mobile blog to follow your blog.
Customization of the color scheme can be done by providing  css file. Can't be done here.
No need to specify the language, It guesses automatically. The same file works for most of the languages. You need to specify the language otherwise it doesn't work and for every different language the different js file is required.
Syntax is highlighted even for the preview of the post. It doesn't work for post preview.
Scroll is not provided for code segment. Code looks awkward if the lines are longer and goes out of current frame. You need to manually divide lines to shorter one so that it fit in current frame. Scroll bar is provided. No manual work is required.
Very few sites use it e.g Google. Most of the sites are using it where RSS feed and mobile version is not used.
Some of the lines can't be highlighted though the line number can be marked. You can highlight lines.

If you are concerned about bandwidth and indexing of your blog on search engine then I suggest you to  choose PrettyPrint. As you may be aware that for the blog which takes longer time to load, the search engine spiders either escape it or rank them lower.

Integration with blogger:

For integrating Prettify, we need to modify the template and put the reference of prettify.js prettify.css in the script tag under Head tag. Steps are given below.

  • Go to the blogger dashboard, then click Template link present on the left-hand-side list, which is marked as 1 in the picture shown below.
  • Once you are on the Template window your dashboard will look similar to the one shown in the picture below. Before modifying the template you can save it and if something goes wrong then you can easily restore the previous template. 
  • To backup the template just press the button which is in the upper right corner and marked as 2  in the picture below. 

Template dashboard of blogger for integrating prettify
Template dashboard

  • Backup/Restore dialog will appear as shown in the picture below. Click download full template and store template in your local machine.

Template Backup/Restore dialog box


  • Again go back to the Template dashboard and click on Edit HTML button. Edit HTML dialog box will appear.


Template Edit HTML dialog box pic1

  • Click Proceed button. This will take you to editor where you can change html code as shown in the picture below.

Template Edit HTML dialog box pic2.


  • Put the following tags in <head> tag section of HTML template.
      <link 
       href="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.css" 
        type="text/css" 
        rel="stylesheet"/>
      <script type="text/javascript" 
       src="http://google-code-prettify.googlecode.com/svn/trunk/src/prettify.js">
      </script> 
      
  • Edit the <body> tag and it should look like as shown below.
     
      <body onload="prettyPrint()"  ... >
     
  • Once you are done, just save the template.

Usage:

  • In your post/blog surround your code with <pre> or <code> tags. as shown below.
      <pre class="prettyprint">...</pre>
                 or 
     <code class="prettyprint">...</code> 
     
your code will look like the following.

Without PrettyPrint With PrettyPrint
         import pretty.print.example;
         class MyprettyPrint{
          public prettyPrint(){
             println("Hello PrettyPrint !!");
          } 
         }
        
         import pretty.print.example;
         class MyprettyPrint{
          public prettyPrint(){
             println("Hello PrettyPrint !!");
          } 
         }
         

If you are interested to know more about Prettyprint, you can find it over here.

Your valuable comments are always welcomed. It will help to improve my post and understanding.
"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Sunday, July 8, 2012

Tutorial on Android Homescreen Widget with AlarmManager.

This is a follow up tutorial on Android widget. If you haven't read it till now then please go through    it before starting this tutorial. You may be aware that AppWidgetProvider's lowest interval is 30 mins. In this tutorial we will learn  to create widget with update interval less than 30 mins using AlarmManager.

New update:

In Android 4.1, a new feature has been introduced for Homescreen widget which enables widget to reorganize its view when resized. To support this feature a new method onAppWidgetOptionsChanged() has been introduced in AppWidgetProvider class. This method gets called in response to the ACTION_APPWIDGET_OPTIONS_CHANGED broadcast when this widget has been layed out at a new size. 

Project Information:  Meta-information about the project.

Platform Version : Android API Level 16.
IDE : Eclipse Helios Service Release 2
Emulator: Android 4.1

Prerequisite: Preliminary knowledge of Android application framework, Intent Broadcast receiver and AlarmManager.

Example with fixed update interval less than 30 mins.

In this tutorial we will create time widget which shows current time. This widget will get updated every second and we will be using AlarmManager for it. Here, repeating alarm is set for one second interval. But in real world scenario, it is not recommended to use one second repeating alarm because it drains the battery fast. You have to follow the similar steps mentioned in previous widget tutorial  to write widget layout file. But this time we are introducing a TextView field in the layout which will display the time. The content of the "time_widget_layout.xml" is given below.
<linearlayout android:background="@drawable/widget_background" 
   android:layout_height="match_parent" android:layout_width="match_parent" 
   android:orientation="vertical" 
   xmlns:android="http://schemas.android.com/apk/res/android">
     <textview android:gravity="center_horizontal|center_vertical" 
          android:id="@+id/tvTime" android:layout_gravity="center" 
          android:layout_height="match_parent" android:layout_margin="4dip" 
          android:layout_width="match_parent" android:textcolor="#000000" 
          style="android: style/TextAppearance.Medium;"/>
</linearlayout>

Follow the same procedure to create the AppWidgetProvider metadata file. The content of metadata file "widget_metadata.xml" is given below.
  <appwidget-provider android:initiallayout="@layout/time_widget_layout" 
        android:minheight="40dp" android:minwidth="130dp"  
        android:updateperiodmillis="1800000" 
        xmlns:android="http://schemas.android.com/apk/res/android">
</appwidget-provider>

In this tutorial, onEnabled(), onDsiabled(), onUpdate() and onAppWidgetOptionsChanged() have been defined unlike the previous widget tutorial where only onUpdate() was defined. 

  • onEnabled(): An instance of AlarmManager is created here to start the repeating timer and register the intent with the AlarmManager.  As this method gets called at the very first instance of widget installation, it helps to set repeating alarm  only once.
  • onDisabled(): In this method, alarm is canceled because this method gets called as soon as the very last instance of widget is removed/uninstalled and we don't want to leave the registered alarm even when it's not being used.
  • onUpdate(): This method updates the time on remote TextView.
  • onAppWidgetOptionsChanged(): This method gets called when the widget is resized.

package com.rakesh.widgetalarmmanagerexample;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.widget.RemoteViews;
import android.widget.Toast;

public class TimeWidgetProvider extends AppWidgetProvider {

 @Override
 public void onDeleted(Context context, int[] appWidgetIds) {
  Toast.makeText(context, "TimeWidgetRemoved id(s):"+appWidgetIds, Toast.LENGTH_SHORT).show();
  super.onDeleted(context, appWidgetIds);
 }

 @Override
 public void onDisabled(Context context) {
  Toast.makeText(context, "onDisabled():last widget instance removed", Toast.LENGTH_SHORT).show(); 
  Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
  PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
  AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
  alarmManager.cancel(sender);
  super.onDisabled(context);
 }

 @Override
 public void onEnabled(Context context) {
  super.onEnabled(context);
  AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
  PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
  //After after 3 seconds
  am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+ 100 * 3, 1000 , pi);
 }

 @Override
 public void onUpdate(Context context, AppWidgetManager appWidgetManager,
   int[] appWidgetIds) {
  ComponentName thisWidget = new ComponentName(context,
    TimeWidgetProvider.class);

  for (int widgetId : appWidgetManager.getAppWidgetIds(thisWidget)) {

   //Get the remote views
   RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
     R.layout.time_widget_layout);
   // Set the text with the current time.
   remoteViews.setTextViewText(R.id.tvTime, Utility.getCurrentTime("hh:mm:ss a"));
   appWidgetManager.updateAppWidget(widgetId, remoteViews);
  }
 }

 @Override
 public void onAppWidgetOptionsChanged(Context context,
   AppWidgetManager appWidgetManager, int appWidgetId,
   Bundle newOptions) {
  //Do some operation here, once you see that the widget has change its size or position.
  Toast.makeText(context, "onAppWidgetOptionsChanged() called", Toast.LENGTH_SHORT).show();
 }
}


Broadcast receiver is defined to handle the intent registered with alarm. This broadcast receiver gets called every second because repeating alarm has been set in the AppWidgetProvider classs for 1 second. Here, onReceive() method has been defined which updates the widget with the current time and getCurrentTime() has been used to get the current time.
package com.rakesh.widgetalarmmanagerexample;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
import android.widget.RemoteViews;
import android.widget.Toast;

public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {

 @Override
 public void onReceive(Context context, Intent intent) {
  PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
  PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
  //Acquire the lock
  wl.acquire();

  //You can do the processing here update the widget/remote views.
  RemoteViews remoteViews = new RemoteViews(context.getPackageName(),
    R.layout.time_widget_layout);
  remoteViews.setTextViewText(R.id.tvTime,  Utility.getCurrentTime("hh:mm:ss a"));
  ComponentName thiswidget = new ComponentName(context, TimeWidgetProvider.class);
  AppWidgetManager manager = AppWidgetManager.getInstance(context);
  manager.updateAppWidget(thiswidget, remoteViews);
  //Release the lock
  wl.release();
 }
}

It's always a good idea to keep utility methods in some utility class which can be accessed from other packages. getCurrentTime() has been defined in the Uitility class. This method is used in AppWidgetProvider and BroadcastReciever classes. 
package com.rakesh.widgetalarmmanagerexample;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

public class Utility {
  public static String getCurrentTime(String timeformat){
      Format formatter = new SimpleDateFormat(timeformat);
         return formatter.format(new Date());
     }
}

In Android manifest file, we need to include WAKE_LOCK permission because wake lock is used in broadcast receiver. AlarmManagerBroadcastReceiver has been registered as broadcast receiver. Remaining part is simple to understand.
  <manifest android:versioncode="1" android:versionname="1.0" 
      package="com.rakesh.widgetalarmmanagerexample" 
      xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-sdk android:minsdkversion="16" android:targetsdkversion="16"/>

<uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application android:icon="@drawable/ic_launcher" 
          android:label="@string/app_name">
        <activity android:label="@string/title_activity_widget_alarm_manager" 
                android:name=".WidgetAlarmManagerActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver android:icon="@drawable/ic_launcher" 
             android:label="@string/app_name"
             android:name=".TimeWidgetProvider">
            <intent-filter>
                <action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
            </intent-filter>
            <meta-data android:name="android.appwidget.provider"  
                android:resource="@xml/widget_metadata"/>
        </receiver>
        <receiver android:name=".AlarmManagerBroadcastReceiver"/>
    </application>
</manifest>

Once the code is executed, the widget gets registered. When you install widget on homescreen, it appears as shown below.
Android Homescreen time widget

you can download source code from here.

Related tutorial:



Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Friday, July 6, 2012

iGoogle will not be available after November 1,2013

Today I was surprised to see this "iGoogle will not be available after November 1,2013", which popped on the iGogole dashboard. iGoogle is going to officially retire on November 1, 2013 where as the mobile version of this website is going to retire soon which is the end of this month, July 31, 2012. According to Google, iGoogle has been eroded over time because Chrome and Android apps have provided similar functionality and have become the most popular among masses. It might not make much difference to most of the readers who are not using the iGoogle. But it will certainly affect those  who have built their applications around this framework. Some of the readers may not be aware that google has some hidden APIs which is built on the igoogle framework  e.g Weather, Stock Exchange, Calendar etc. And these APIs have been used by the developers. Now developers and other concerned users have only 16 months left to do transition to other application/platform.

iGoogle will not be available after November 1, 2012


iGoogle also has blog-feed readers which helps to boost up the blog indexing. If this feature goes away with the iGoogle then definitely bloggers have to look for other resort to improve the blog indexing. 
Those using iGoogle  might be worried about their data. Their personal data will continue to exist with other Google applications, i.e Gmail, Google Calendar, Google Finance, Google Drive, etc. 



Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Tutorial on Android AlaramManager

While writing an application, need arises to schedule execution of code in future. You may require AlarmManager to schedule your work at a specified time. AlarmManager accesses to system alarm and schedules the execution of code even when the application is not running.

Project Information:  Meta-information about the project.

Platform Version : Android API Level 10.
IDE : Eclipse Helios Service Release 2
Emulator: Android 4.1

Prerequisite: Preliminary knowledge of Android application framework, and Intent Broadcast receiver.

AlarmManager:

AlarmManager has access to the system alarm services. With the help of AlarmManager you can schedule execution of code in future. AlarmManager object can't instantiate directly however it can be retrieved by calling Context.getSystemService(Context.ALARM_SERVICE). AlarmManager is always registered with intent. When an alarm goes off, the Intent which has been registered with AlarmManager, is broadcasted by the system automatically. This intent starts the target application if it is not  running. It is recommended to use AlarmManager when you want your application code to be run at a specific time, even if your application is not currently running. For other timing operation handler should be used because it is easy to use. Handler is covered in other tutorial.

Method Description
set() Schedules an alarm for one time.
setInexactRepeating() Schedules an alarm with inexact repeating. Trigger time doesn't follow any strict restriction.
setRepeating() Schedules an alarm with exact repeating time.
setTime() Sets the system's wall clock time.
setTimeZone() Sets the system's default time zone.
Check out the AlarmManager documention for more info.

In this tutorial let's learn to create one-time timer and the repeating timer, and also to cancel the repeating timer. Here timer and alarm have been used interchangeably, but in this tutorial context both of them have the same meaning.

Example Code:

Let's create three buttons start repeating timer, cancel repeating timer and one-time timer in the layout file. These buttons are attached with methods i.e startRepeatingTimer, cancelRepeatingTimer and onetimeTimer respecitively. These methods will be defined in the Activity class. The layout file is shown below(activity_alarm_manager.xml).
 <linearlayout android:layout_height="match_parent" 
    android:layout_width="match_parent" android:orientation="vertical" 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools">

    <button android:id="@+id/btStart" android:layout_height="wrap_content" 
      android:layout_width="match_parent" android:onclick="startRepeatingTimer" 
      android:padding="@dimen/padding_medium" android:text="@string/btStart"   
      tools:context=".WidgetAlarmManagerActivity"/>
    <button android:id="@+id/btCancel" android:layout_height="wrap_content" 
      android:layout_width="match_parent" android:onclick="cancelRepeatingTimer"  
      android:padding="@dimen/padding_medium" android:text="@string/btCancel" 
      tools:context=".WidgetAlarmManagerActivity"/>
     <button android:id="@+id/btOneTime" android:layout_height="wrap_content" 
     android:layout_width="match_parent" android:onclick="onetimeTimer" 
     android:padding="@dimen/padding_medium" android:text="@string/btOneTime"   
     tools:context=".WidgetAlarmManagerActivity"/>
   </linearlayout>

We are going to define the BroadcastReciever which handles the intent registered with AlarmManager. In the given class onReceive() method has been defined. This method gets invoked as soon as intent is received. Once we receive the intent we try to get the extra parameter associated with this intent. This extra parameter is user-defined i.e ONE_TIME, basically indicates whether this intent was associated with one-time timer or the repeating one. Once the ONE_TIME parameter value has been extracted, Toast message is  displayed accordingly. Helper methods have also been defined, which can be used from other places with the help of objects i.e setAlarm(), cancelAlarm() and onetimeTimer() methods. These methods can also be defined somewhere else to  do operation on the timer i.e set, cancel, etc. To keep this tutorial simple, we have defined it in BroadcastReceiver.


setAlarm(): This method sets the repeating alarm by use of setRepeating() method. setRepeating() method needs four arguments:

  1. type of alarm, 
  2. trigger time: set it to the current time
  3. interval in milliseconds: in this example we are passing 5 seconds ( 1000 * 5 milliseconds)
  4. pending intent: It will get registered with this alarm. When the alarm gets triggered the pendingIntent will be broadcasted.

cancelAlarm(): This method cancels the previously registered alarm by calling cancel() method. cancel() method takes pendingIntent as an argument. The pendingIntent should be matching one, only then the cancel() method can remove the alarm from the system.

onetimeTimer(): This method creates an one-time alarm. This can be achieved by calling set() method. set() method takes three arguments:

  1. type of alarm
  2. trigger time 
  3. pending intent


package com.rakesh.alarmmanagerexample;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.PowerManager;
import android.widget.Toast;

public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {

 final public static String ONE_TIME = "onetime";

 @Override
 public void onReceive(Context context, Intent intent) {
   PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
         PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "YOUR TAG");
         //Acquire the lock
         wl.acquire();

         //You can do the processing here.
         Bundle extras = intent.getExtras();
         StringBuilder msgStr = new StringBuilder();
         
         if(extras != null && extras.getBoolean(ONE_TIME, Boolean.FALSE)){
          //Make sure this intent has been sent by the one-time timer button.
          msgStr.append("One time Timer : ");
         }
         Format formatter = new SimpleDateFormat("hh:mm:ss a");
         msgStr.append(formatter.format(new Date()));

         Toast.makeText(context, msgStr, Toast.LENGTH_LONG).show();
         
         //Release the lock
         wl.release();
         
 }

 public void SetAlarm(Context context)
    {
        AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
        intent.putExtra(ONE_TIME, Boolean.FALSE);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
        //After after 5 seconds
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 5 , pi); 
    }

    public void CancelAlarm(Context context)
    {
        Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
        PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
        alarmManager.cancel(sender);
    }

    public void setOnetimeTimer(Context context){
     AlarmManager am=(AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
        intent.putExtra(ONE_TIME, Boolean.TRUE);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
        am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pi);
    }
}


Given below is the manifest file. Here, WAKE_LOCK permission is required because the wake lock is being used while processing in onReceive() method present in AlarmManagerBroadcastReceiver class. AlarmManagerBroadcastReceiver has been registered as broadcast receiver.
<manifest android:versioncode="1" android:versionname="1.0" 
       package="com.rakesh.alarmmanagerexample" 
       xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-sdk android:minsdkversion="10" android:targetsdkversion="15"/>
    
<uses-permission android:name="android.permission.WAKE_LOCK"/>
    <application android:icon="@drawable/ic_launcher" 
       android:label="@string/app_name" android:theme="@style/AppTheme">
        <activity android:label="@string/title_activity_alarm_manager" 
           android:name="com.rakesh.alarmmanagerexample.AlarmManagerActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN">

                <category android:name="android.intent.category.LAUNCHER">
            </category>
           </action>
          </intent-filter>
        </activity>
        <receiver android:name="com.rakesh.alarmmanagerexample.AlarmManagerBroadcastReceiver">
        </receiver>
    </application>
</manifest>

Now let's define the activity class which defines some methods. These methods are going to handle the button clicks. Here in this class we create an instance of AlarmManagerBroadcastReciever which will help us to access setAlarm(), cancelAlarm() and setOnetime(). Rest of the code is easy to understand.

package com.rakesh.alarmmanagerexample;

import com.rakesh.alarmmanagerexample.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
import android.support.v4.app.NavUtils;

public class AlarmManagerActivity extends Activity {

 private AlarmManagerBroadcastReceiver alarm;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_alarm_manager);
        alarm = new AlarmManagerBroadcastReceiver();
    }
    
    @Override
 protected void onStart() {
  super.onStart();
 }

    public void startRepeatingTimer(View view) {
     Context context = this.getApplicationContext();
     if(alarm != null){
      alarm.SetAlarm(context);
     }else{
      Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
     }
    }
    
    public void cancelRepeatingTimer(View view){
     Context context = this.getApplicationContext();
     if(alarm != null){
      alarm.CancelAlarm(context);
     }else{
      Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
     }
    }
    
    public void onetimeTimer(View view){
     Context context = this.getApplicationContext();
     if(alarm != null){
      alarm.setOnetimeTimer(context);
     }else{
      Toast.makeText(context, "Alarm is null", Toast.LENGTH_SHORT).show();
     }
    }
    
 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_widget_alarm_manager, menu);
        return true;
    }
}
Once you are done with the coding, just execute the project and you will find the similar kind of application running in your emulator.
AlarmManagerExample is installed in application list AlarmManager:Onetime timer is triggered

Please download AlarmManagerExample code, if you need reference code.
Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius

Thursday, July 5, 2012

Python package/library source code browsing.


Recently I moved to new project where the programming language was Python. I often get confused about what module do I need to import ? what is the signature of the method/function? etc. I also tried to consult the documentation provided by the third party library but many a times I didn't get the clear idea. 
However, Java provides javadoc which helps to figure out the type of package that needs to be included in a particular class. It also describes the function signature. This is possible because of good editors(IDE: Eclipse) with integrated javadoc. On the other hand Python editors lack these features. Most of the Python IDEs neither help to auto-complete nor provide any help for the method/function signature. This makes life more difficult and frustrating. Python third party library/module provides their documentation but sometimes much more is needed which can sufficed through access to source code. This helps to understand how third party library functions and gives a very first hand experience on how the code is organized, what modules are needed to be included in the project in order to access certain objects, methods, or classes, what is the method signature etc. If you have access to such information your life becomes easier while coding in Python. 
Bitten by source code browsing bug I started looking for tool which can help me to browse python library source code and I stumbled upon pydoc.net and Nullege.com.  First we will talk about  pydoc.net and then will talk about Nullege(Don't get confused with pydoc module present in python). Let's see what pydoc.net says about itself in its own words:

"PyDoc.net is an online open source package library for Python language. It aims to provide ease of navigation through their source code in a better and organized way. It is still on its experimental stages."


 I have been using this tool for quite sometime and liked it. It provides very limited functionality e.g indexing, searching and source code.  If you are too geeky and know the technology well then in that case it might be useful. But if you are a newbie then this is not what you are looking for. If pydoc.net had provided similar functionality  as grepcode has provided for java source code, then pydoc.net would be definitely the first choice for Python developers . If you are wondering about grepcode and it functionality, then you may be interested to check this post.  Since grepcode doesn't provide python module source code, I have to settle with pydoc. Given that pydoc.net is experimental project and handled by single person, I would give this site 3.5 out of 5.
Enough of talking, lets check its functionality. This site provides search service, where you can search by keyword, package/module name and will list the related packages and modules. Checkout the  picture below. It also lists the packages download count wise. There is one more list which shows the packages/modules with their respective tags as marked 2 in the picture below. 
Pydoc: search result for package or modules
module search result
If you click the link "index package" which is marked 4  in the above picture, it lists all the packages in alphanumeric wise which you can see in the shown below. This gives you idea about the similar packages and the gamut of package who share common prefix/name.

pydoc: alphanumerically indexed python packages
Module/package index
Ok found the package name so what? Well this was the first step on the source code browsing. On selecting the package it shows the meta-data of the package/module as shown in the picture below. This also shows how to install the package, example-code and the documentation link. In some cases it also shows the link from where the source code can be downloaded.
pydoc: Python module/package details, example, how to install etc.
Package/module details
As you may have noticed there is a directory hierarchy which shows how modules are organized and what are the source files present under any particular directory. If you click the file name you will see the source code which will look similar to picture as shown below.
pydoc: source code of module

Nullege also has the similar interface as that of pydoc. You can see the user interface in picture below. I noticed few differences between these two websites. Nullege doesn't give any meta information about the package and doesn't show the documentation provided by the python third party library/package. But Nullege has the feature to search the keywords in the source code while pydoc doesn't have.

Nullege: user interface, with package structure and source code.
User may not like one thing about Nullege i.e the advertisements are shown below the source code hierarchy which restrict the complete view of directory hierarchy. If the advertisements were shown somewhere else, it would have given more view area to the directory/file hierarchy and hence would have provided good user experience. If asked, I would give 3 out of 5 to this website.

How to download source code:

If you are interested in downloading the source code, even that is possible with the help of "pip". Pip is a python tool which installs the python packages and it's replacement of easy_install. If you system doesn't have the pip installed then run the following command.
 
$python easy_install pip

For downloading source code of particular package run the following command.
 
 $pip install -src= . <package-name>   #This will download the src in the current directory.

Happy source code browsing!!!

Related topics:
Android/java source code browsing

Your valuable comments are always welcomed. It will help to improve my post and understanding.

"By three methods we may learn wisdom: First, by reflection, which is noblest; Second, by imitation, which is easiest; and third by experience, which is the bitterest."
By : Confucius