Pages

Monday, June 6, 2011

Display a marker on MapView, using Overlays.

Expends from last exercise, AndroidMapper. A marker is shown on the current location using Overlays, if MapView started with location, Mode 1.



To use Overlays, a class of InterestingLocations have to be created, extends ItemizedOverlay.

It involve modification on AndroidMapView.java

package com.AndroidMapper;

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

import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.ItemizedOverlay;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.OverlayItem;

public class AndroidMapView extends MapActivity {

  private TextView myLongitude, myLatitude;
  private CheckBox mySatellite;
  
  private MapView myMapView;
  private MapController myMapController;
 
  private void SetSatellite()
  {
   myMapView.setSatellite(mySatellite.isChecked());
  };
  
 @Override
 protected void onCreate(Bundle icicle) {
  // TODO Auto-generated method stub
  super.onCreate(icicle);
  setContentView(R.layout.mymapview);
  
  Bundle bundle = this.getIntent().getExtras();
        int Mode = bundle.getInt("Mode");
  
  myMapView = (MapView)findViewById(R.id.mapview);
  myMapController = myMapView.getController();  
  myMapView.setBuiltInZoomControls(true);
  
  myLongitude = (TextView)findViewById(R.id.longitude);
  myLatitude = (TextView)findViewById(R.id.latitude);
  mySatellite = (CheckBox)findViewById(R.id.satellite);
  mySatellite.setOnClickListener(mySatelliteOnClickListener);
  
  SetSatellite();
  
   
  if(Mode == 1)
  {
   int intLatitude = bundle.getInt("Latitude");
   int intLongitude = bundle.getInt("Longitude");
   GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
   CenterLocation(initGeoPoint);
  
   Drawable marker=getResources().getDrawable(
     android.R.drawable.ic_menu_myplaces);
   marker.setBounds(0, 0, marker.getIntrinsicWidth(), 
     marker.getIntrinsicHeight());
   myMapView.getOverlays().add(new InterestingLocations(marker, 
     intLatitude, intLongitude));
  }
 }

 @Override
 protected boolean isRouteDisplayed() {
  // TODO Auto-generated method stub
  return false;
 }
 
 private void CenterLocation(GeoPoint centerGeoPoint)
 {
  myMapController.animateTo(centerGeoPoint);

  myLongitude.setText("Longitude: "+
    String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000)
    );
  myLatitude.setText("Latitude: "+
    String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000)
    );
 };
 
 private CheckBox.OnClickListener mySatelliteOnClickListener =
    new CheckBox.OnClickListener(){

     public void onClick(View v) {
      // TODO Auto-generated method stub
      SetSatellite();
     }
 };
 
 class InterestingLocations extends ItemizedOverlay<OverlayItem>{
  
  private List<OverlayItem> locations = 
   new ArrayList<OverlayItem>();
  private Drawable marker;

  public InterestingLocations(Drawable defaultMarker, 
    int LatitudeE6, int LongitudeE6) {
   super(defaultMarker);
   // TODO Auto-generated constructor stub
   this.marker=defaultMarker;
   // create locations of interest
   GeoPoint myPlace = new GeoPoint(LatitudeE6,LongitudeE6);
   locations.add(new OverlayItem(myPlace , 
     "My Place", "My Place"));
   populate();
  }

  @Override
  protected OverlayItem createItem(int i) {
   // TODO Auto-generated method stub
   return locations.get(i);
  }

  @Override
  public int size() {
   // TODO Auto-generated method stub
   return locations.size();
  }

  @Override
  public void draw(Canvas canvas, MapView mapView, 
    boolean shadow) {
   // TODO Auto-generated method stub
   super.draw(canvas, mapView, shadow);
   
   boundCenterBottom(marker);
  }
 }
}


Download the files.

Exercise AndroidMapper, Android Application using MapView

In the previous exercises, the MapView track the GPS and center on it repeatly. In this exercise, AndroidMapper, it will not track on GPS. Instead, there are three options to center in starting of the MapView.
- Default: Start ViewMap without any center location.
- GPS: It's the current GPS (which will be track before ViewMap start). If no valid GPS, this option will be disable.
- Location: User input location. If no location input, this option will be disable.



After ViewMap loaded, user can move the Map, Zoom-in/out using MapView's BuiltInZoomControls.



This application is not yet finished, more feature (or bug fixed) will be added in the furture.

Create a Android Application named, AndroidMapper.
Package Name: com.AndroidMapper
Target Google Platform 2.0 with Google APIs.

Modify main.xml to have the UI as seen in the picture.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
/>
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RadioButton
android:id="@+id/option_default"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Default Location" />
<RadioButton
android:id="@+id/option_gps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="GPS:" />
<RadioButton
android:id="@+id/option_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Location:" />
</RadioGroup>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="latitude"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/latitude"
android:inputType="numberDecimal"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="longitude"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/longitude"
android:inputType="numberDecimal"
/>
<Button
android:id="@+id/loadmap"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Load Map"
/>
</LinearLayout>


Modify AndroidMapper.java
package com.AndroidMapper;

import com.google.android.maps.GeoPoint;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RadioButton;

public class AndroidMapper extends Activity {

private LocationManager myLocationManager;
private LocationListener myLocationListener;
private GeoPoint GeoPoint_GPS, GeoPoint_Location;

RadioButton myoption_default, myoption_gps, myoption_location;
EditText mylatitude, mylongitude;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);

  loadMenu();
  validGPS();
  validLocation();

  myLocationManager = (LocationManager)getSystemService(
       Context.LOCATION_SERVICE);

  myLocationListener = new MyLocationListener();

  myLocationManager.requestLocationUpdates(
       LocationManager.GPS_PROVIDER,
       0,
       0,
       myLocationListener);
}

private void loadMenu()
{
setContentView(R.layout.main);
myoption_default = (RadioButton)findViewById(R.id.option_default);
myoption_gps = (RadioButton)findViewById(R.id.option_gps);
myoption_location = (RadioButton)findViewById(R.id.option_location);
mylatitude = (EditText)findViewById(R.id.latitude);
mylongitude = (EditText)findViewById(R.id.longitude);

mylatitude.setOnKeyListener(locationOnKeyListener);
mylongitude.setOnKeyListener(locationOnKeyListener);

Button myLoadMapButton = (Button)findViewById(R.id.loadmap);
myLoadMapButton.setOnClickListener(myLoadMapButtonOnClickListener);
}

Button.OnClickListener myLoadMapButtonOnClickListener =
new Button.OnClickListener(){

  @Override
  public void onClick(View v) {
   // TODO Auto-generated method stub
   if(myoption_default.isChecked()){
    OpenIntentAndroidMapView(null);
   }
   else if(myoption_gps.isChecked()){
    OpenIntentAndroidMapView(GeoPoint_GPS);
   }
   else if(myoption_location.isChecked()){
    OpenIntentAndroidMapView(GeoPoint_Location);
   }
   else{
    OpenMissingOptionDialog();
   }
   
  }

};

private void OpenIntentAndroidMapView(GeoPoint startLocation)
{
Intent intent = new Intent();
  intent.setClass(AndroidMapper.this, AndroidMapView.class);

  Bundle bundle = new Bundle();

  if (startLocation == null)
  {
   bundle.putInt("Mode", 0);
  }
  else
  {
   bundle.putInt("Mode", 1);
   bundle.putInt("Longitude", startLocation.getLongitudeE6());
   bundle.putInt("Latitude", startLocation.getLatitudeE6());
  }

  intent.putExtras(bundle);
startActivityForResult(intent, 0);
}

private void OpenMissingOptionDialog()
{
 new AlertDialog.Builder(this)
 .setTitle("missing selection")
 .setMessage("Please select one of the option")
 .setPositiveButton("OK",
  new DialogInterface.OnClickListener()
  {
   public void onClick(DialogInterface dialoginterface, int i)
    {}
  })
 .show();
}

EditText.OnKeyListener locationOnKeyListener =
new EditText.OnKeyListener(){

  @Override
  public boolean onKey(View v, int keyCode, KeyEvent event) {
   // TODO Auto-generated method stub
   validLocation();
   return false;
  }

};

private void validGPS()
{
GeoPoint_GPS = loadGPS();
if (GeoPoint_GPS==null)
{
 myoption_gps.setClickable(false);
}
else
{
 myoption_gps.setText("GPS: (" +
   String.valueOf((float)GeoPoint_GPS.getLatitudeE6()/1000000) +" : " +
   String.valueOf((float)GeoPoint_GPS.getLongitudeE6()/1000000) +")");
 myoption_gps.setClickable(true);
}
}

private void validLocation()
{
/*
Toast.makeText(AndroidMapper.this,
  mylatitude.getText().toString(),
  Toast.LENGTH_LONG).show();*/
if (mylatitude.getText().toString().equals("") || mylongitude.getText().toString().equals(""))
{

 myoption_location.setText("Location: ");
 myoption_location.setClickable(false);
 myoption_location.setChecked(false);
}
else
{
 float locationLatitude = Float.parseFloat(mylatitude.getText().toString());
 float locationLongitude = Float.parseFloat(mylongitude.getText().toString());

 myoption_location.setText("Location: (" +
   String.valueOf(locationLatitude) +" : " +
   String.valueOf(locationLongitude) +")");
 myoption_location.setClickable(true);
 myoption_location.setChecked(true);

 GeoPoint_Location = new GeoPoint(
          (int)(locationLatitude*1000000),
          (int)(locationLongitude*1000000));
}
}

private GeoPoint loadGPS()
{
//Get the current location from GPS
myLocationManager = (LocationManager)getSystemService(
     Context.LOCATION_SERVICE);
Location initLocation=myLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(initLocation != null)
  {
   return (
     new GeoPoint(
          (int)(initLocation.getLatitude()*1000000),
          (int)(initLocation.getLongitude()*1000000)));
  }
else
 return null;
}

private class MyLocationListener implements LocationListener{

 @Override
 public void onLocationChanged(Location location) {
  // TODO Auto-generated method stub
  GeoPoint_GPS = new GeoPoint(
        (int)(location.getLatitude()*1000000),
        (int)(location.getLongitude()*1000000));
  myoption_gps.setText("GPS: (" +
   String.valueOf((float)GeoPoint_GPS.getLatitudeE6()/1000000) +" : " +
   String.valueOf((float)GeoPoint_GPS.getLongitudeE6()/1000000) +")");
 myoption_gps.setClickable(true);
 }

 @Override
 public void onProviderDisabled(String provider) {
  // TODO Auto-generated method stub
 
 }

 @Override
 public void onProviderEnabled(String provider) {
  // TODO Auto-generated method stub
 
 }

 @Override
 public void onStatusChanged(String provider, int status, Bundle extras) {
  // TODO Auto-generated method stub
 
 }

}
}


Modify mymapview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
 <CheckBox
  android:id="@+id/satellite"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text=" Satellite "
 />
 </LinearLayout>
 <LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
 <TextView
  android:id="@+id/longitude"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Longitude:"
  />
  <TextView
   android:id="@+id/latitude"
   android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="Latitude:"
  />
 </LinearLayout>
</LinearLayout>
<com.google.android.maps.MapView
 android:id="@+id/mapview"
 android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
 android:apiKey="-----Your Own API Key here-------------"
/>
</LinearLayout>
You have to Obtaining a Maps API Key, and insert into the field "apikey"

Modify AndroidMapView.java
package com.AndroidMapper;

import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.TextView;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;

public class AndroidMapView extends MapActivity {

 private TextView myLongitude, myLatitude;
 private CheckBox mySatellite;

 private MapView myMapView;
 private MapController myMapController;

 private void SetSatellite()
 {
  myMapView.setSatellite(mySatellite.isChecked());
 };

@Override
protected void onCreate(Bundle icicle) {
 // TODO Auto-generated method stub
 super.onCreate(icicle);
 setContentView(R.layout.mymapview);

 Bundle bundle = this.getIntent().getExtras();
  int Mode = bundle.getInt("Mode");

 myMapView = (MapView)findViewById(R.id.mapview);
 myMapController = myMapView.getController();
 myMapView.setBuiltInZoomControls(true);

 myLongitude = (TextView)findViewById(R.id.longitude);
 myLatitude = (TextView)findViewById(R.id.latitude);
 mySatellite = (CheckBox)findViewById(R.id.satellite);
 mySatellite.setOnClickListener(mySatelliteOnClickListener);

 SetSatellite();


 if(Mode == 1)
 {
  int intLatitude = bundle.getInt("Latitude");
  int intLongitude = bundle.getInt("Longitude");
  GeoPoint initGeoPoint = new GeoPoint(intLatitude, intLongitude);
  CenterLocation(initGeoPoint);
 }
 
 
}



@Override
protected boolean isRouteDisplayed() {
 // TODO Auto-generated method stub
 return false;
}

private void CenterLocation(GeoPoint centerGeoPoint)
{
 myMapController.animateTo(centerGeoPoint);


 myLongitude.setText("Longitude: "+
   String.valueOf((float)centerGeoPoint.getLongitudeE6()/1000000)
   );
 myLatitude.setText("Latitude: "+
   String.valueOf((float)centerGeoPoint.getLatitudeE6()/1000000)
   );
};

private CheckBox.OnClickListener mySatelliteOnClickListener =
   new CheckBox.OnClickListener(){

    public void onClick(View v) {
     // TODO Auto-generated method stub
     SetSatellite();
    }
};

}


Also modify AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.AndroidMapper"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
  <activity android:name=".AndroidMapper"
            android:label="@string/app_name">
      <intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
  </activity>
  <activity android:name=".AndroidMapView">
   </activity>
<uses-library android:name="com.google.android.maps" />
</application>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-sdk android:minSdkVersion="5" />

</manifest>


Download the files.

Cannot complete the install because one or more required items could not be found

I tried to install Android SDK and Eclipse Galileo on a fresh ubuntu 9.10 and found the error while installing ADT Plugin for Eclipse:

Cannot complete the install because one or more required items could not be found.
Software being installed: Android Development Tools 0.9.4.v200910220141-17704 (com.android.ide.eclipse.adt.feature.group 0.9.4.v200910220141-17704)
Missing requirement: Android Development Tools 0.9.4.v200910220141-17704 (com.android.ide.eclipse.adt.feature.group 0.9.4.v200910220141-17704) requires 'org.eclipse.wst.xml.core 0.0.0' but it could not be found


It's because there are some components missed in the setup, and the Galileo update site is not in the list of Available Software Sites.

To solve the problem:
Add "http://download.eclipse.org/releases/galileo" in the Available Software Sites.

Install Android SDK release 3 on Eclipse 3.5 Galileo, in Ubuntu 9.10

Both Adroid SDK and ubuntu have new release recently. There is a little bit variation in installation from the old version, so I re-write the installation procedure here. In this article, Eclipse 3.5 Galileo with Android SDK release 3 (for Android 2) will be installed on a fresh new ubuntu 9.10.

Environment:
OS: Linux ubuntu 9.10 for desktop or laptop (http://www.ubuntu.com/)
Eclipse: Eclipse 3.5 Galileo (bundled with ubuntu 9.10)
Android SDK: Android SDK release 3 (http://developer.android.com/)

Install Java:

Start a Terminal and type the command:
$ sudo apt-get install sun-java6-jdk


For Ubuntu 10.04 LTS, refer the article "How to install sun-java6-jdk on Ubuntu 10.04 LTS?" - Android Er@2010-05-04 -


Download Android SDK:

Download Android SDk release 3 from http://developer.android.com/sdk/index.html, extract to any folder you want. In my case, it is $home/android-sdk-linux/

Install Eclipse:

In ubuntu 9.10, Eclipse 3.5.1 is bundled currently. To install Eclipse on ubuntu, it can be downloaded from http://www.eclipse.org/, installe using Ubuntu Software Center (Application->Ubuntu Software Center in ubuntu menu bar), or installed using Synaptic Package Manager (System->Administration->Synaptic Package Manager in ubuntu menu bar). I tried install using the download version and Ubuntu Software Center, both cannot be installed without error, so Synaptic Package Manager is suggested to install Eclipse.
Involve Synaptic Package Manager from System->Administration of Ubuntu top menu.


Type Eclipse in te Quick search box, select eclipse in the list and mark for installation.


Additional required changes are listed, click Mark to accept.


Click Apply to start installation


Installing the ADT Plugin

Start Eclipse, Click Help->Install New Software... from the top menu.

Click Available Software Sites to check if http://download.eclipse.org/releases/galileo is available. If not, add it.

Add a new site https://dl-ssl.google.com/android/eclipse/



Select https://dl-ssl.google.com/android/eclipse/, and wait a moment. The available will be listed. click to select it and click Next.


Click Next again


Accept the terms and click Finish.


Wait, you will be asked for security warning, click OK.


Wait installation to finish, and accept re-start after finished.

Setup Android SDT inside Eclipse:

Click Window->Preference in Eclipse top menu.

Select Android on the left, and browse to your Android SDK folder, it's $home/android-sdk-linux/ in my setup.


Install Package:

Click Window->Android SDK and AVD Manager

Click Available Package from the left, expend and select your expected packages, and click Install Selected.


Accept All, and Install Accepted.


Restart Again.

Create AVD:
Refer to the article http://z4android.blogspot.com/2011/06/create-android-virtual-device-avd-in.html

Now, the installation is finished.

Thursday, June 2, 2011

Displaying the List of video files Stored in SD card and playing the video

The folowing example used to list all the video files stored in SDcard and you can
play the video by selecting the file from list.

AndroidManifest.xml
--------------------
<?xml version="1.0" encoding="utf-8"?>
< manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="sample.video" android:versionCode="1" android:versionName="1.0.0">
      < uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
      < application android:icon="@drawable/icon" android:label="@string/app_name">
            < activity android:name=".VideoActivity" android:label="@string/app_name">
                  < intent-filter>
                        < action android:name="android.intent.action.MAIN" />
                        < category android:name="android.intent.category.LAUNCHER"/>
                  < /intent-filter>
            </activity>
            < activity android:name=".ViewVideo">
                  < intent-filter>
                        < action android:name="android.intent.action.VIEW" />
                        < category android:name="android.intent.category.DEFAULT" />
                  </intent-filter>
            </activity>
      </application>
</manifest>


main.xml
--------
<?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical" android:layout_width="fill_parent"
      android:layout_height="fill_parent">
      < ListView
            android:id="@+id/PhoneVideoList"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"/>
</LinearLayout>

VideoActivity.java
-------------------
package sample.video;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class VideoActivity extends Activity {
      private Cursor videocursor;
      private int video_column_index;
      ListView videolist;
      int count;

      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            init_phone_video_grid();
      }

      private void init_phone_video_grid() {
            System.gc();
            String[] proj = { MediaStore.Video.Media._ID,
MediaStore.Video.Media.DATA,
MediaStore.Video.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE };
            videocursor = managedQuery(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
            count = videocursor.getCount();
            videolist = (ListView) findViewById(R.id.PhoneVideoList);
            videolist.setAdapter(new VideoAdapter(getApplicationContext()));
            videolist.setOnItemClickListener(videogridlistener);
      }

      private OnItemClickListener videogridlistener = new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position,
long id) {
                  System.gc();
                  video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DATA);
                  videocursor.moveToPosition(position);
                  String filename = videocursor.getString(video_column_index);
                  Intent intent = new Intent(VideoActivity.this, ViewVideo.class);
                  intent.putExtra("videofilename", filename);
                  startActivity(intent);
            }
      };

      public class VideoAdapter extends BaseAdapter {
            private Context vContext;

            public VideoAdapter(Context c) {
                  vContext = c;
            }

            public int getCount() {
                  return count;
            }

            public Object getItem(int position) {
                  return position;
            }

            public long getItemId(int position) {
                  return position;
            }

            public View getView(int position, View convertView, ViewGroup parent) {
                  System.gc();
                  TextView tv = new TextView(vContext.getApplicationContext());
                  String id = null;
                  if (convertView == null) {
                        video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME);
                        videocursor.moveToPosition(position);
                        id = videocursor.getString(video_column_index);
                        video_column_index = videocursor
.getColumnIndexOrThrow(MediaStore.Video.Media.SIZE);
                        videocursor.moveToPosition(position);
                        id += " Size(KB):" + videocursor.getString(video_column_index);
                        tv.setText(id);
                  } else
                        tv = (TextView) convertView;
                  return tv;
            }
      }
}



ViewVideo.java
---------------
package sample.video;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.MediaController;
import android.widget.VideoView;

public class ViewVideo extends Activity {
      private String filename;
      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            System.gc();
            Intent i = getIntent();
            Bundle extras = i.getExtras();
            filename = extras.getString("videofilename");
            VideoView vv = new VideoView(getApplicationContext());
            setContentView(vv);
            vv.setVideoPath(filename);
            vv.setMediaController(new MediaController(this));
            vv.requestFocus();
            vv.start();
      }
}

Displaying the List of music files Stored in SD card and playing music in the background

The foolowing example used to list all the music files stored in SDcard and you can play the music
in the backgroung by selecting the file from list.

main.xml
--------
<?xml version="1.0" encoding="utf-8"?>
< LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical" android:layout_width="fill_parent"
      android:layout_height="fill_parent">
      < ListView
            android:id="@+id/PhoneMusicList"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"/>
</LinearLayout>

MusicActivity.java
-------------------
package sample.music;

import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.provider.MediaStore;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.AdapterView.OnItemClickListener;

public class MusicActivity extends Activity {
      ListView musiclist;
      Cursor musiccursor;
      int music_column_index;
      int count;
      MediaPlayer mMediaPlayer;

      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            init_phone_music_grid();
      }

      private void init_phone_music_grid() {
            System.gc();
            String[] proj = { MediaStore.Audio.Media._ID,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DISPLAY_NAME,
MediaStore.Video.Media.SIZE };
            musiccursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
proj, null, null, null);
            count = musiccursor.getCount();
            musiclist = (ListView) findViewById(R.id.PhoneMusicList);
            musiclist.setAdapter(new MusicAdapter(getApplicationContext()));

            musiclist.setOnItemClickListener(musicgridlistener);
            mMediaPlayer = new MediaPlayer();
      }

      private OnItemClickListener musicgridlistener = new OnItemClickListener() {
            public void onItemClick(AdapterView parent, View v, int position,
long id) {
                  System.gc();
                  music_column_index = musiccursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
                  musiccursor.moveToPosition(position);
                  String filename = musiccursor.getString(music_column_index);

                  try {
                        if (mMediaPlayer.isPlaying()) {
                              mMediaPlayer.reset();
                        }
                        mMediaPlayer.setDataSource(filename);
                        mMediaPlayer.prepare();
                        mMediaPlayer.start();
                  } catch (Exception e) {

                  }
            }
      };

      public class MusicAdapter extends BaseAdapter {
            private Context mContext;

            public MusicAdapter(Context c) {
                  mContext = c;
            }

            public int getCount() {
                  return count;
            }

            public Object getItem(int position) {
                  return position;
            }

            public long getItemId(int position) {
                  return position;
            }

            public View getView(int position, View convertView, ViewGroup parent) {
                  System.gc();
                  TextView tv = new TextView(mContext.getApplicationContext());
                  String id = null;
                  if (convertView == null) {
                        music_column_index = musiccursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
                        musiccursor.moveToPosition(position);
                        id = musiccursor.getString(music_column_index);
                        music_column_index = musiccursor
.getColumnIndexOrThrow(MediaStore.Audio.Media.SIZE);
                        musiccursor.moveToPosition(position);
                        id += " Size(KB):" + musiccursor.getString(music_column_index);
                        tv.setText(id);
                  } else
                        tv = (TextView) convertView;
                  return tv;
            }
      }
}

How to Display Thumbnails of Images Stored in the SD Card

Using the following example we can display the thumbnails of images stored in the sd card. Here im displaying the thumbnails in the Grid view.
You should to add the folowing permission in the manifest xml file.
< uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
Sd card should be available with the emulator or real device.

ImageThumbnailsActivity is the main Activity.

AndroidManifest.xml
--------------------
<?xml version="1.0" encoding="utf-8"?>
< manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="image.Thumbnails" android:versionCode="1" android:versionName="1.0.0">
      < uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
      < application android:icon="@drawable/icon" android:label="@string/app_name">
            < activity android:name=".ImageThumbnailsActivity"
                  android:label="@string/app_name">
                  < intent-filter>
                        < action android:name="android.intent.action.MAIN" />
                        < category android:name="android.intent.category.LAUNCHER"/>
                  </intent-filter>
            </activity>
            < activity android:name=".ViewImage">
                  < intent-filter>
                        < action android:name="android.intent.action.VIEW" />
                        < category android:name="android.intent.category.DEFAULT" />
                  </intent-filter>
            </activity>
      </application>
</manifest>

package image.Thumbnails;

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

public class ImageThumbnailsActivity extends Activity {
      /** Called when the activity is first created. */
      private Cursor imagecursor, actualimagecursor;
      private int image_column_index, actual_image_column_index;
      GridView imagegrid;
      private int count;
      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            init_phone_image_grid();
      }
      private void init_phone_image_grid() {
            String[] img = { MediaStore.Images.Thumbnails._ID };
            imagecursor = managedQuery(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, img, null,
null, MediaStore.Images.Thumbnails.IMAGE_ID + "");
            image_column_index = imagecursor
.getColumnIndexOrThrow(MediaStore.Images.Thumbnails._ID);
            count = imagecursor.getCount();
            imagegrid = (GridView) findViewById(R.id.PhoneImageGrid);
            imagegrid.setAdapter(new ImageAdapter(getApplicationContext()));
            imagegrid.setOnItemClickListener(new OnItemClickListener() {
                  public void onItemClick(AdapterView parent, View v,
int position, long id) {
                        System.gc();
                        String[] proj = { MediaStore.Images.Media.DATA };
                        actualimagecursor = managedQuery(
MediaStore.Images.Media.EXTERNAL_CONTENT_URI, proj,
null, null, null);
                        actual_image_column_index = actualimagecursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                        actualimagecursor.moveToPosition(position);
                        String i = actualimagecursor.getString(actual_image_column_index);
                        System.gc();
                        Intent intent = new Intent(getApplicationContext(), ViewImage.class);
                        intent.putExtra("filename", i);
                        startActivity(intent);
                  }
            });
      }


      public class ImageAdapter extends BaseAdapter {
            private             Context mContext;
            public ImageAdapter(Context c) {
                  mContext = c;
            }
            public int getCount() {
                  return count;
            }
            public Object getItem(int position) {
                  return position;
            }
            public long getItemId(int position) {
                  return position;
            }
            public View getView(int position,View convertView,ViewGroup parent) {
                  System.gc();
                  ImageView i = new ImageView(mContext.getApplicationContext());
                  if (convertView == null) {
                        imagecursor.moveToPosition(position);
                        int id = imagecursor.getInt(image_column_index);
                        i.setImageURI(Uri.withAppendedPath(
MediaStore.Images.Thumbnails.EXTERNAL_CONTENT_URI, ""
+ id));
                        i.setScaleType(ImageView.ScaleType.CENTER_CROP);
                        i.setLayoutParams(new GridView.LayoutParams(92, 92));
                  }
                  else {
                        i = (ImageView) convertView;
                  }
                  return i;
            }
      }
}

// By selecting the thumbnails user can view the actual image.
package image.Thumbnails;

import android.os.Bundle;
import android.widget.ImageView;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class ViewImage extends Activity {
      private String filename;
      @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            System.gc();
            Intent i = getIntent();
            Bundle extras = i.getExtras();
            BitmapFactory.Options bfo = new BitmapFactory.Options();
            bfo.inSampleSize = 2;
            filename = extras.getString("filename");
            ImageView iv = new ImageView(getApplicationContext());
            Bitmap bm = BitmapFactory.decodeFile(filename, bfo);
            iv.setImageBitmap(bm);
            setContentView(iv);
      }
}



//main.xml

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

How to download and display Images in android

/*
This example helps you to display the remote images in android. The progress bar will be displayed when application downloading the image. Progress bar will be stopped when the download completes and the Image will be displayed. This is also a good example for using thread in the background.. I Hope it helps..
*/

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URL;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;

public class ViewStorageImage extends Activity {
      private String url;
      ImageView iv;
      Thread t;
      Bitmap bm;
      ProgressDialog dialog;
       @Override
      public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            showDialog(0);
            setContentView(R.layout.storageimage);
            url = "http://.........";//enter the url here..
            iv=(ImageView)findViewById(R.id.storageactualimage);
            t=new Thread() {
                  public void run() {
                        viewImage();
                  }
            };
            t.start();
      }
      @Override
      protected Dialog onCreateDialog(int id) {
            switch (id) {
                  case 0: {
                        dialog = new ProgressDialog(this);
                        dialog.setMessage("Please wait while loading...");
                        dialog.setIndeterminate(true);
                        dialog.setCancelable(true);
                        return dialog;
                  }
            }
            return null;
      }
      private Handler handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                  Bitmap image=(Bitmap)msg.obj;
                  ImageView iv=new ImageView(this);
                  iv.setImageBitmap(image);
                  setContentView(iv);
            }
      };
      public void viewImage() {
            try {
                  URL myURL = new URL(url);
                  final BufferedInputStream bis = new BufferedInputStream(myURL.openStream(), 1024);
                  final ByteArrayOutputStream dataStream = new ByteArrayOutputStream();
                  BufferedOutputStream out = new BufferedOutputStream(dataStream,1024);
                  copy(bis, out);
                  out.flush();
                  final byte[] data = dataStream.toByteArray();
                  BitmapFactory.Options bfo = new BitmapFactory.Options();
                  bfo.inSampleSize = 2;
                  bm = BitmapFactory.decodeByteArray(data, 0, data.length, bfo);
                  bis.close();
                  removeDialog(0);
                  Message myMessage=new Message();
                  myMessage.obj=bm;
                  handler.sendMessage(myMessage);
            }
            catch (Exception e) {
                  finish();
            }
      }
      static final int BUFF_SIZE = 1024;
      static final byte[] buffer = new byte[BUFF_SIZE];
      public static void copy(BufferedInputStream in, BufferedOutputStream out) throws IOException {
            try {
                  while (true) {
                              synchronized (buffer) {
                              int amountRead = in.read(buffer);
                              if (amountRead == -1) {
                                    break;
                              }
                              out.write(buffer, 0, amountRead);
                        }
                  }
            }
            catch(Exception e){
                  if (in != null) {
                        in.close();
                  }
                  if (out != null) {
                        out.close();
                  }
            }
            finally {
                  if (in != null) {
                        in.close();
                  }
                  if (out != null) {
                        out.close();
                  }
            }
      }
}

Allows Android applications to open network sockets: "android.permission.INTERNET"

If your Android application need to access Internet, you have to grand permission to open network sockets.

Add the code <uses-permission android:name="android.permission.INTERNET" /> in AndroidManifest.xml,

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.exercise.AndroidTwitterClient"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".AndroidTwitterClient"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

    </application>
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.INTERNET" />
</manifest> 

EditText for password, inputType="textPassword"


I'm going to make a exercise of Twitter Client to post update status to Twitter. In which I need a EditText, with hiden input of password.

To achieve it, EditText with android:inputType="textPassword" can be used.The input characters will be displayed as password dots instead of themselves.

Alternatively, android:password="true" can be used. But it is deprecated and not suggested.







<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:gravity="center_horizontal"
    android:text="User Name and Password"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="User Name:"
    />
<EditText  
    android:id="@+id/username"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Password:"
    />
<EditText  
    android:id="@+id/password"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:inputType="textPassword"
    />
<TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="What are you doing?"
    />
<EditText  
    android:id="@+id/whatareyoudoing"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    />
<Button  
    android:id="@+id/mySubmit"
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center_horizontal"
    android:text="Submit"
    />
</LinearLayout>

Simulate Animation, using Runnable Thread

After the articles, Display a drawable graph, using ImageView and AndroidRunnable, with Runnable Thread, now we can try to simulate animation using setImageResource(), inside handleMessage() which are trigged by a Runnable Thread. A circle arrow rotate in duration of 1000ms.

This exercise extends from the previous article, AndroidRunnable, with Runnable Thread.




Save the four graphics, used to form the animation of a rotating arrow, in the /res/drawable/ folder.



Add a ImageView in main.xml to display the animation.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   >
<TextView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="@string/hello"
   />
<TextView 
   android:id="@+id/i"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   />
<ImageView
   android:id="@+id/myImageView"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:scaleType="center"
   />
</LinearLayout>


Modify update_i() to change i, and load ViewImage with arrow_01, arrow_02, arrow_03 and arrow_04 one by one.
package com.exercise.AndroidRunnable;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import android.widget.TextView;

public class AndroidRunnable extends Activity{
 
 int i = 0;
 TextView myi;
 ImageView MyImageView;
 
 Handler handler = new Handler(){

  @Override
  public void handleMessage(Message msg) {
   // TODO Auto-generated method stub
   update_i();
  }
 };
 
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);

myi =(TextView)findViewById(R.id.i);
MyImageView = (ImageView)findViewById(R.id.myImageView);
}

@Override
 protected void onStart() {
  // TODO Auto-generated method stub
  super.onStart();
  
  Thread myThread=new Thread(new Runnable() {
   public void run() {
    while(true){
     try {
      handler.sendMessage(handler.obtainMessage());
      Thread.sleep(1000);
     }
     catch (Throwable t) {
     }
    }
   }
  });
   
  myThread.start();
 }

 private void update_i()
{
 switch(i){
 case 0:
  i++;
 MyImageView.setImageResource(R.drawable.arrow_01);
  break;
 case 1:
  i++;
 MyImageView.setImageResource(R.drawable.arrow_02);
  break;
 case 2:
  i++;
 MyImageView.setImageResource(R.drawable.arrow_03);
  break;
 case 3:
  i = 0;
 MyImageView.setImageResource(R.drawable.arrow_04);
  break;
 }
 myi.setText(String.valueOf(i));
}
}
AndroidRunnable.java can be downloaded here.

For sure, it's not a good practice to implement animation. It is used to show the implementation of Runnable Thread, and Handle.

Here is another article about Animation background, using animation-list and AnimationDrawable.

Animation background, using animation-list and AnimationDrawable

In the article Simulate Animation, using Runnable Thread, I described how to simulate animation using Runnable Thread. For sure, it's not a good practice. In this article I show how to implement animation using animation-list and AnimationDrawable.


The animation can be started and stopped by the two button, Start and Stop.

- Save the four graphics, used to form the animation of a rotating arrow, in the /res/drawable/ folder.



- Create a file named arrow_animation.xml in /res/drawable
<animation-list
  xmlns:android="http://schemas.android.com/apk/res/android"
  >
  <item android:drawable="@drawable/arrow_01" android:duration="100" />
  <item android:drawable="@drawable/arrow_02" android:duration="100" />
  <item android:drawable="@drawable/arrow_03" android:duration="100" />
  <item android:drawable="@drawable/arrow_04" android:duration="100" />
</animation-list>


- Modify main.xml to add two Button to Start and Stop animation
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent"
  >
<TextView
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:text="@string/hello"
  />
<Button
     android:id="@+id/myStartButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Start"
     />
<Button
     android:id="@+id/myStopButton"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:text="Stop"
     />
<ImageView
     android:id="@+id/myImageView"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
     />
</LinearLayout>


- Modify the Java code as:
package com.exercise.AndroidAnimationDrawable;

import android.app.Activity;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class AndroidAnimationDrawable extends Activity {

  AnimationDrawable AniFrame;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
   
      Button MyStartButton = (Button)findViewById(R.id.myStartButton);
      MyStartButton.setOnClickListener(MyStartButtonOnClickListener);
      Button MyStopButton = (Button)findViewById(R.id.myStopButton);
      MyStopButton.setOnClickListener(MyStopButtonOnClickListener);
   
      ImageView MyImageView = (ImageView)findViewById(R.id.myImageView);
      MyImageView.setBackgroundResource(R.drawable.arrow_animation);
      AniFrame = (AnimationDrawable) MyImageView.getBackground();
  }

  Button.OnClickListener MyStartButtonOnClickListener =
      new Button.OnClickListener(){
          @Override
          public void onClick(View v) {
              // TODO Auto-generated method stub
              AniFrame.start();
          }
  };

  Button.OnClickListener MyStopButtonOnClickListener =
      new Button.OnClickListener(){
          @Override
          public void onClick(View v) {
              // TODO Auto-generated method stub
              AniFrame.stop();
          }
  };

}


----------------------------------------
In the book of Professional Android Application Development (Wrox Programmer to Programmer) by Reto Meier, it's stated that:

At the time of going to print, there is a bug in the AnimationDrawable class. Currently, AnimationDrawable resources are not properly loaded until some time after an Activity’s onCreate method has completed. Current work-arounds use timers to force a delay before loading a frame-by-frame resource.



I have the same problem; if AniFrame.start() is called inside onCreate() immediately, the animation cannot start. That's why I add the buttons to start and stop the operation.

Popular Posts