Showing posts with label Developer Tutorial. Show all posts
Showing posts with label Developer Tutorial. Show all posts

Thursday, May 20, 2010

Image Switcher View | Android Developer Tutorial


Now we will explore ImageSwitcher View. It is a view useful to switch smoothly between two images and thus provides ways of transitioning from one to another through appropriate animations.

We will implement the same concept of showing a gallery of images that scrolls at the top of the android screen landscape and upon selection of one image, it gets displayed as a larger image in the lower part through the use of an ImageSwitcher. This is what I had done earlier in the GalleryView tutorial but now instead of showing the selected picture through an ImageView, I will show it using a ImageSwitcher. Though the output may seem very similar, lot of other methods are available on the ImageSwitcher that can be used, if required.

Here is how the output would look (NOTE that I have not used the default gallery background provided by Android in the Gallery images)


So, to begin with, first we need to declare the layout xml to have a gallery and the ImageSwitcher:

<Gallery
      android:id="@+id/Gallery01"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"></Gallery>
<ImageSwitcher
      android:id="@+id/ImageSwitcher01"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
</ImageSwitcher>

The next thing that we need to do is create a class that not only extends Activity but also implements ViewFactory. The ViewFactory is a Interface that creates views that need to be shown in the ImageSwitcher. So it has one method makeView() which we need to implement. It is here that we can set the attributes of the ImageView that would be shown within the ImageSwitcher -  like its background, it scale, its layout parameters etc. – typically those attributes that we would have otherwise statically set through a layout xml.

Here is the class declaration and the method makeView():

public class ImageSwitcherView extends Activity implements ViewFactory {

and
      @Override
      public View makeView() {
            ImageView iView = new ImageView(this);
            iView.setScaleType(ImageView.ScaleType.FIT_CENTER);
            iView.setLayoutParams(new
                        ImageSwitcher.LayoutParams(
                                    LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
            iView.setBackgroundColor(0xFF000000);
            return iView;
      }
This alone is the real difference from the Gallery example.

Other smaller things we need to do is get a handle to the ImageSwitcher in the onCreate() method:

            iSwitcher = (ImageSwitcher) findViewById(R.id.ImageSwitcher01);
            iSwitcher.setFactory(this);
            iSwitcher.setInAnimation(AnimationUtils.loadAnimation(this,
                        android.R.anim.fade_in));
            iSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this,
                        android.R.anim.fade_out));

Here we also set the animation on how the image should fly in and fly out of the area. Then, we get a handle to the gallery and set an ImageAdapter to it. The ImageAdpater is as described in my Gallery Example. If you have not seen that, please go through that and then try this example, as I would not want to repeat myself here.
Now on the click of a gallery image, we would want to pass the selected image to the ImageSwitcher and this is what we do here:

            gallery.setOnItemClickListener(new OnItemClickListener() {

                  @Override
                  public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
                        iSwitcher.setImageResource(pics[arg2]);
                  }
            });
      }

Monday, May 17, 2010

Table of contents

Table of Contents:
  1. Android Fundamentals - Jargon Explained
  2. Preliminary Step: Eclipse set up / Create Android Project
  3. Android Explicit Intent Example
  4. Android Implicit Intent Example
  5. Invoking Android Pre-packaged Applications
  6. Fetching a result from a called activity
  7. Android Notifications Example
  8. Android Local Service Example
  9. Android Service and Notification Combined Example
  10. Android Remote Service Example
  11. Android Content Provider Example
  12. Android Broadcast Receiver Example
  13. Android SQLite DB Example
  14. Shared Preferences on Android
  15. Google Maps on Android
  16. Location Manager on Android
  17. Simple List View
  18. Custom List View
  19. Android Threads and Handlers
  20. Http Connection Using Threads
  21. Date Time Picker Views
  22. Auto Complete Text View
  23. Spinner View
  24. Gallery View
  25. Image Switcher View
  26. Creating Android UI Programmatically
  27. Android UI - Inflate from XML (Dynamic UI Creation)
  28. ListView of Data from SQLiteDatabase
  29. TabLayout or Tabbed View
  30. Options Menu
  31. Context Menu
  32. New Contacts Content Provider
    Titbits
    1. Simulating an incoming call on the Emulator
    2. Obtain Google Maps API Key
    3. Simulate Location Change in Android Emulator
    4. Updating to Android SDK 2.1
    5. Delete / Remove Applications deployed on the Android Emulator
    6. Disable Chinese / Japanese Characters on Emulator Keyboard
    7. Android Eclipse link Error - New Project
    All Sample code at One place / Alternate Download site for Code

    Wednesday, May 5, 2010

    Http Connection Using Threads & Handlers in Android (Part 19)

    This is about how to invoke an Http Url from an android activity. If you have already written such a program in core java, you will not find anything new in the HTTP connectivity part. However, this tutorial also shows how to communicate between thread using the Message object.


    In this tutorial, I plan to download 1 image and 1 text from the internet on the click of respective buttons on the android phone.

    NOTE: I have also incidentally used Absolute Layout so that the buttons, the text and the image are all seen on the same screen even after being fetched.

    Since fetching data from the internet can be a time-consuming task and a very unpredictable one at that, so, it would best be done in a separate thread rather than the UI/main thread. The basics of this have been discussed in the previous tutorial on Handlers and Threads.

    To go to the application code directly, on the click of a button “Get Image”, I want to get an image whose URL is hard-coded in the program. For that first, I must open an HTTP connection to the server and then request for the image.

    Hence is the code for opening and making an HTTP Connection:

    private InputStream openHttpConnection(String urlStr) {
    InputStream in = null;
    int resCode = -1;
    try {


    URL url = new URL(urlStr);
    URLConnection urlConn = url.openConnection();

    if (!(urlConn instanceof HttpURLConnection)) {
    throw new IOException ("URL is not an Http URL");
    }

    HttpURLConnection httpConn = (HttpURLConnection)urlConn;
    httpConn.setAllowUserInteraction(false);
    httpConn.setInstanceFollowRedirects(true);
    httpConn.setRequestMethod("GET");
    httpConn.connect();
    resCode = httpConn.getResponseCode();


    if (resCode == HttpURLConnection.HTTP_OK) {
    in = httpConn.getInputStream();
    }
    } catch (MalformedURLException e) {
    e.printStackTrace();
    } catch (IOException e) {
    e.printStackTrace();
    }
    return in;
    }
    I will not be explaining this code much as most of this is based on the java.net package. This code would be exactly same even if we were to write this in regular java code, not meant for android usage. In brief, I have opened a URLConnection, checked if it is an instance of HttpURLConnection, set the parameters required and made the ‘connection’ finally by calling the connect() method. Then, I check if the response code is OK and I get a handle to the input stream.


    So, this is a utility method that I will use for fetching image as well as text.

    Now, coming to fetching the image. I want to fetch it when the end user clicks on a button “Get Image”. So the code associated with the button click is here:

    getImageButton = (Button)findViewById(R.id.Button01);
    getImageButton.setOnClickListener( new OnClickListener() {
    Override
    public void onClick(View v) {
    downloadImage(http://www.android.com/media/wallpaper/gif/android_logo.gif);
                                  }
                   });

    So the fetching of the image is in the downloadImage() method, which is given the URL of the android logo. Here is the method:

    private void downloadImage(String urlStr) {
    progressDialog = ProgressDialog.show(this, "", "Fetching Image...");
    final String url = urlStr;
    new Thread() {
    public void run() {
    InputStream in = null;
    Message msg = Message.obtain();
    msg.what = 1;
    try {
    in = openHttpConnection(url);
    bitmap = BitmapFactory.decodeStream(in);
    Bundle b = new Bundle();
    b.putParcelable("bitmap", bitmap);
    msg.setData(b);
    in.close();
    } catch (IOException e1) {
    e1.printStackTrace();
    }
    messageHandler.sendMessage(msg);

    }
    }.start();
    This method looks a bit complicated. First, let us look at the basics. If I were not fetching this in a separate thread, I would have just the 3 lines of code that is in Bold and highlighted. Open a connection, fetch the bitmap and close the connection. However, since this is a typical task that is unpredictable in its response time, it is best done in a separate thread of its own. So, before I start a new thread, I let the UI thread to show a ProgressDialog as shown in

    progressDialog = ProgressDialog.show(this, "", "Fetching Image...");

    Then, I start a new thread. I make the URL string accessible within the new thread by making it a final variable. Since message is an object that I can use for communication between threads, I create a Message object in the thread. Then, I set the message number to 1, so that I can use it later.
    Message msg = Message.obtain();
    msg.what = 1;
    Then, I bundle my bitmap already fetched into a Bundle object that can be sent back in the Message object.
    Bundle b = new Bundle();
    b.putParcelable("bitmap", bitmap);
    msg.setData(b);

    Once I close the input stream as in:
     in.close();
    the thread has completed the job. So, I notify the main / UI thread through this method and also pass on the Message object:
    messageHandler.sendMessage(msg);
    This completes the fetching of the image in a separate thread. Now, how do I retrieve the image from the Message object in the main thread?
    As soon as the child thread notifies, the method called back in the main thread is the handleMessage(msg) method. It is in this method that I retrieve the bitmap and set it to the ImageView in the UI. Here it goes:


    private Handler messageHandler = new Handler() {
    public void handleMessage(Message msg) {
    super.handleMessage(msg);
    switch (msg.what) {
    case 1:
    ImageView img = (ImageView) findViewById(R.id.imageview01);
    img.setImageBitmap((Bitmap)(msg.getData().getParcelable("bitmap")));
    break;
    case 2:
        ……….
    }
    progressDialog.dismiss();
    }
            };

    Within this method, first I check the msg.what variable to see what the type of message I am expecting is. If it is 1, which I had set in downloadImage(..) method, then, I do the required things to get a handle to the ImageView object and then give the bitmap to it.

    How do I fetch the data from the msg object? Through getData(). Then I use the key “bitmap” to retrieve the bitmap and cast it to Bitmap before setting it to the ImageView. Finally, I dismiss the progress dialog.

    I hope this is clear. This example not only shows HTTP Connection from Android but also the Thread-to-thread communication through handler, message exchange.

    In a very similar fashion, I also fetch the text. On click of the Get Text button, here is the code that gets invoked:
    getTextButton.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
    downloadText(http://saigeethamn.blogspot.com/feeds/posts/default);
    }
             });

    The downloadText() code is here:

    private void downloadText(String urlStr) {
    progressDialog = ProgressDialog.show(this, "", "Fetching Text...");
    final String url = urlStr;
    new Thread () {
    public void run() {
    int BUFFER_SIZE = 2000;
    InputStream in = null;
    Message msg = Message.obtain();
    msg.what=2;
    try {
    in = openHttpConnection(url);
    InputStreamReader isr = new InputStreamReader(in);
    int charRead;
    text = "";
    char[] inputBuffer = new char[BUFFER_SIZE];
    while ((charRead = isr.read(inputBuffer))>0)
    {
    //---convert the chars to a String---
    String readString =
    String.copyValueOf(inputBuffer, 0, charRead);
    text += readString;
    inputBuffer = new char[BUFFER_SIZE];
    }
    Bundle b = new Bundle();
    b.putString("text", text);
    msg.setData(b);
    in.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
    messageHandler.sendMessage(msg);
    }
    }.start();
    }

    And the way the text is handled in the main thread handleMessage(..) method is here:
    case 2:
    TextView text = (TextView) findViewById(R.id.textview01);
    text.setText(msg.getData().getString("text"));
    break;
    The complete code can be downloaded here

     NOTE: the blog editor is posing major problems in editing - it is jumbling up the whole post esp. when I use the " feature. So, please bear with me if somethings look garbled. I have tried my best to work around the editor problem. This has been noticed only in the last 3 posts of mine. Hope it gets fixed soon.
    Thanks for your understanding.

    Monday, October 12, 2009

    Shared Preferences | Android Developer Tutorial (Part 13)


    We saw in an earlier tutorial (Part 12) how data can be stored in SQLDB. However, many applications may provide a way to capture user preferences on the settings of a specific application or an activity. For supporting this, Android provides a simple set of APIs.


    Preferences are typically name value pairs. They can be stored as “Shared Preferences” across various activities in an application (note currently it cannot be shared across processes). Or it can be something that needs to be stored specific to an activity (which is not discussed here).


    The context object lets you retrieve SharedPreferencesthrough the method Context.getSharedPreferences().


    In my example, I will set 2 preferences i.e. MyNameand MyWallpaperin one activity i.e ManageSharedPref.java. Retrieve these values in the next activity – ViewSharedPrefs.java. The second activity displays my preferred name in a list view and also resets the android wallpaper to the image that I had set as a preferred wallpaper in the first activity. When you run this application, if you come back to the home, you will see the wall paper is reset.


    Here is the code in ManageSharesPrefs:


    SharedPreferences myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
            SharedPreferences.Editor prefsEditor = myPrefs.edit();
            prefsEditor.putString(MY_NAME, "Sai");
            prefsEditor.putString(MY_WALLPAPER, "f664.PNG");
            prefsEditor.commit();
           
    First, I obtain a SharedPreferences object making it readable by all. The first parameter is a name of a file that stores my preferences. This automatically creates the xml file if it does not exist and then stores in the same.


    Next, I edit it. That creates an editor object, using which I input my preferences. Here, for the wall paper, I have put an image name. I also need to push the actual image file into the android storage which I do this way.


    adb push <local> <remote>


    In this case it is


    adb push f664.PNG /data/misc/wallpaper/f664.PNG


    This command creates a folder called wallpaper in /data/misc and copies the f664.PNG file from my current location to the android storage.


    When I click the “View Shared Preferences” button, I am taken to the next activity. Here is the code in ViewSharedPrefs that gets executed:


            SharedPreferences myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
            String prefName = myPrefs.getString(MY_NAME, "nothing");
            String wallPaper = myPrefs.getString(MY_WALLPAPER, null);
           
            if(wallPaper != null) {
                try {
                      Bitmap bm = BitmapFactory.decodeFile("/data/misc/wallpaper/"+wallPaper);
                      Log.d(getClass().getSimpleName(),"Wallpaper name is: "+ wallPaper);
                      setWallpaper(bm);
                      Toast.makeText(this, "Wall paper has been changed." +
                                  "You may go to the home screen to view the same", Toast.LENGTH_LONG).show();
                } catch (FileNotFoundException fe){
                      Log.e(getClass().getSimpleName(),"File not found");
                } catch (IOException ie) {
                      Log.e(getClass().getSimpleName()," IO Exception");
                }
               
            }
            ArrayList<String> results = new ArrayList<String>();
            results.add("Your Preferred name is: " + prefName);
          this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,results));

    There are 3 steps to understand here:


    1.    Step 1: Retrieve the shared prefs data from the object.


            SharedPreferences myPrefs = this.getSharedPreferences("myPrefs", MODE_WORLD_READABLE);
            String prefName = myPrefs.getString(MY_NAME, "nothing");
            String wallPaper = myPrefs.getString(MY_WALLPAPER, null);

    2.    Step 2: Display the name
            ArrayList<String> results = new ArrayList<String>();
            results.add("Your Preferred name is: " + prefName);
          this.setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1,results));

    3.    Step 3: Reset the wall paper.
            if(wallPaper != null) {
                try {
                      Bitmap bm = BitmapFactory.decodeFile("/data/misc/wallpaper/"+wallPaper);
                      Log.d(getClass().getSimpleName(),"Wallpaper name is: "+ wallPaper);
                      setWallpaper(bm);
                      Toast.makeText(this, "Wall paper has been changed." +
                                  "You may go to the home screen to view the same", Toast.LENGTH_LONG).show();
                } catch (FileNotFoundException fe){
                      Log.e(getClass().getSimpleName(),"File not found");
                } catch (IOException ie) {
                      Log.e(getClass().getSimpleName()," IO Exception");
                }
               
            }
    It is this simple. The complete code is available here.