Monday, July 18, 2011

Simple ListView Adapter and list item select

When you are using a listview in your applications many a times you will write your own adapter to display items in a listview. But if your list is very simple showing a list of strings, you can use inbuilt adapters like ArrayAdapter, SimpleCursorAdapter etc.

ArrayAdapter
Let us look at an example

<?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:layout_height="wrap_content" 
android:id="@+id/listView1" 
android:layout_width="match_parent"
 
android:layout_margin="20dp"
></ListView>
</LinearLayout>

And the oncreate function of activity reads like this

       super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        String []s = new String[]{"Lorem","Ipsum","dolor","sit","amet"};
        ListView lv = (ListView)findViewById(R.id.listView1);
        lv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,s));

So this arrayadapter just needs the array to be displayed in the list, the context and the textview resource id. Instead of defining another resource id, I have used in built resource. Now our list looks like this

If you want to change the appearance of your list, you can define your own list view as shown.
Add another xml file with just a textview . Do not use any layout.
tv.xml

<TextView android:text="TextView" android:id="@+id/textView1"
android:background="#0489B1"
android:textColor="#000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="20dp"
android:padding="5dp"></TextView>
Now use this as layout in arrayadpter
 lv.setAdapter(new ArrayAdapter<String>(this, R.layout.tv,s));


And after you set the background color of linear layout in main to blue, this is how your list looks like


Next step will be write a listener to the list. You should attach an OnItemClickListener to this listview.

 lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
 ListView lv = (ListView) arg0;
 TextView tv = (TextView) lv.getChildAt(arg2);
 String s = tv.getText().toString();
 Toast.makeText(SamplesActivity.this, "Clicked item is"+s, Toast.LENGTH_LONG).show();
} });
Instead of Toasting, you can perform any required processing. 
What if you want to use the list for selecting one of the items? Again the simplest way to use this is to use android.R.layout.simple_list_item_single_choic

       lv.setAdapter(new ArrayAdapter<String>(this,android.R.layout.simple_list_item_single_choice,s));
        lv.setChoiceMode(ListView.CHOICE_MODE_SINGLE);   
Now our list lets us select exactly one item
I did change the background color of linear layout to blue in main.xml because the builtin android layouts show list elements in white text which will be invisible if the background is also white.
How do you find out which item is selected from the listview? 
Let us use a button, on click of which we will display the selected item of the list
Modified main.xml is

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#0489B1" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:orientation="vertical">


<ListView android:layout_height="wrap_content" android:id="@+id/listView1"
android:layout_width="match_parent" android:divider="#00ffffff"
android:dividerHeight="10dp" android:layout_margin="20dp"></ListView>
<Button android:text="OK" android:id="@+id/button1"
android:layout_width="wrap_content" 
android:layout_height="wrap_content" 
android:layout_gravity="center_horizontal"></Button>
</LinearLayout>


Let us add the button and onclicklistener to it.

        btn =(Button) findViewById(R.id.button1);
        btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
int p =  lv.getCheckedItemPosition();
String s = ((TextView) lv.getChildAt(p)).getText().toString(); Toast.makeText(SamplesActivity.this, "Selected item is "+s, Toast.LENGTH_LONG).show();
}
});
So now our list looks like this.




Finally let us see how to select multiple elements from the list. 
First of all change the list mode multiple select


lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);


Then we should use lv.setCheckedItemPositions() which returns a sparseboolean array. The array elements are true if that item is selected



btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
SparseBooleanArray sp = lv.getCheckedItemPositions();
StringBuffer str = new StringBuffer();
for(int i=0;i<sp.size();i++){
if(sp.valueAt(i)==true){
String s = ((TextView) lv.getChildAt(i)).getText().toString();
str = str.append(" "+s);
}
}  
Toast.makeText(SamplesActivity.this, "Selected items are "+str.toString(), Toast.LENGTH_LONG).show();
}
});
And, our multi select list is ready!

Saturday, June 18, 2011

Generate Random Numbers in Android

In your apps (especially in game apps) , you may come across the need to generate random numbers. For generation of psuedo random numbers you can use random class from package java.util

First of all you can construct a random number generator using this

        mRandom = new Random(seed);

The seed should be unique for better results. You can use current time for that

                    Time t = new Time();
        t.setToNow();
        mRandom = new Random(t.toMillis(false));

Now to generate a random number from 0 to n, you can use mRandom.nextInt(n). Make sure that n is not zero.
          int rand = mRandom.nextInt(10);

The above line generates a random number between 0 to 9.

Random class also provides other functions such as nextFloat(), nextDouble, nextLong.

Thursday, June 9, 2011

How to publish your android app in Android market

I faced some difficulties when trying to publish my app. So I thought this post may help others.
First you need to have a google account. Then you should pay 25$ (US dollars 25) fees for registration with your credit card.
Next step will be creation of your android app. That is relatively easy. ;-)
But remember your app must have version code and version name. 
Next step is signing your app. This must be done by creating a cryptographic key for your app. To do this you can use the java command keytool.
Again this command at command prompt may give a problem. May be class path variable is not set properly. No problem. You can still go to your jdk directory, then bin subdirectory within  that. Now you have your keytool command. 
You can use the keytool command like
keytool -genkey -v -keystore your-keystore-name -alias your-alias-name -keyalg RSA -keysize 2048 -validity 10000
You must provide a password for the keystore.
Once key is generated, you can go to eclipse IDE and use the option EXPORT in the context menu of project (right click on project name) . You will be prompted for project name, keystore name and location and its password. You should also give the alias name and password and apk file name and location. The apk thus generated is the signed app which can be published into market.
Funnily for me I used to get the error saying the key is not valid till future. I tried many times without much success. Then I realized the reason could because of time zone in India is the cause. So I changed my system date to 1 day in past. Then created the key again. This hack worked. 
You should also upload two screen shots of the app.
Finished all these steps? Published also? Now keep your fingers crossed and pray that people will download and install your app. :-) 

ViewSwitcher in Android - switching layouts for activity

Let us say you want to change the layout in same activity e.g. you want to show a list of urls and when one of them is clicked, you want to show webview on the entire screen. One solution could be to use a dialog, but a dialog will not use the screen area effectively.
In such cases you can use ViewSwitcher.  A viewswitcher can have two child views and only one of them is shown at a time.
The two views you want to use must be wrapped in the viewswitcher  as shown in the xml file below.
<?xml version="1.0" encoding="utf-8"?>
<ViewSwitcher
   xmlns:android="http://schemas.android.com/apk/res/android"
       android:id = "@+id/viewswitcher"
   ---
   -----
>
 <LinearLayout
    android:layout_width="fill_parent"
    ------->
   
    <GridView 
        android:layout_width="fill_parent"
         -------------------
        ------------------->
    </GridView>     
</LinearLayout>
<LinearLayout
    android:layout_width="fill_parent"
     ------------------>
   
    <WebView
    android:layout_width="fill_parent"
   ---------------------->
    </WebView>
 </LinearLayout>
 
</ViewSwitcher>

In this xml file, the two linear layouts are child views of view switcher. One of them has a gridview and the other has a webview.

Add this line in your onCreate function of the activity to get the viewSwitcher from xml

mViewSwitcher = (ViewSwitcher)findViewById(R.id.viewSwitcher1);

To start with, first child view will be shown. Now you can display the other child view, in this case webview by calling viewswitcher.showNext() and viewswitcher.showPrevious()

        public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {
            -------
            mViewSwitcher.showNext();
                               -------
        }
@Override
    public void onBackPressed(){
        if(mWebView.isShown()){
             mViewSwitcher.showPrevious();
           ---------
        }
    }


Saturday, March 26, 2011

Using samsung android phone with windows xp

I have a Samsung galaxy 551. I tried connecting it to the pc. I am supposed to install the driver for it. The installation cd had keis on it. Anyway I tried installing it. It should one or two errors, but completed installing,
  When I ran this Keis, it is not showing my phone even though I have connected the phone using usb.  Nor am I seeing it in "my computers". I tried tethering usb from the phone. The windows usb wizard would say " New device found" and give installation instruction. But it will finally say installation failed as there is no driver  samsung android. I tried uninstalling and reinstalling keiss 2-3 times.
  Now I remembered one of the errors I got during installation of Keiss was "unable to find samsung usb driver for android.exe or something of that type. So I googled for that file and downloaded it from the site http://fr.gsmlibrary.com/Products+Support/Z3X/Samsung+files/Samsung+Box/SAMSUNG_USB_Driver_for_Mobile_Phones.exe.html
and installed it.
and then as if my magic, the keiss start showing the dialog, connecting to the device and windows desktop showed the icon "Found the samsung device..." and then " installation success". So finally my pc was able to detect my phone. Eureka.
Then.... then I went to kitchen to finish my little bit of cooking, when I came back, the phone was asking me to connect to keis. And I could explore all the files of my phone and transfer files to the phone. I copied one of my programs - apk files and then clicked it on the phone. Phone installed the apk file. Double Eureka.!!!!

Thursday, March 24, 2011

Tabs with different background colors

For past 3 days I was trying to have different colors for android tabs instead of normal grey and whitish grey. I got an articles from net android tabs like iphone. Now I am unable to find the article now. Anyways, here is the code

View view = new MyView(this, R.drawable.custombutton, R.drawable.custombutton, "Channels");
       //         channelTabSpec = tabhost.newTabSpec("channels").setIndicator(view)
        .setContent(intent);
 tabhost.addTab(channelTabSpec);
---
----
---

Similarly I created two more tabs Newspapers and Techsites. The class MyView used above is 

private class MyView extends LinearLayout {
          ImageView iv;
          TextView tv;
          public MyView(Context c, int drawable, int drawableselec, String label) {
           super(c);
         
           tv = new TextView(c);
           tv.setText(label);
          
           tv.setGravity(Gravity.CENTER);
           tv.setBackgroundColor(Color.TRANSPARENT);
           tv.setTextColor(Color.WHITE);
           tv.setTextSize(14);
          
           tv.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,
             LayoutParams.WRAP_CONTENT, (float) 1.0));
           setOrientation(LinearLayout.VERTICAL);
           Drawable d = getResources().getDrawable(drawableselec);
           tv.setBackgroundDrawable(d);
          
            addView(tv);
        
          }
         }

I have created a file custombutton.xml in the folder /res/drawable for having different appearances for the normal tab and selected tab. Here is the file

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="false">
        <shape>
            <gradient android:startColor="@color/darkblue"  android:centerColor="@color/lightblue"
                android:endColor="@color/darkblue" android:angle="270" />
            <stroke android:width="1dp" android:color="@color/lightblue" android:radius="1dp"/>
             <corners android:radius="5dp" />
            <padding android:left="1dp" android:top="20dp"
                android:right="1dp" android:bottom="20dp" />
        </shape>
    </item>
    <item android:state_selected="true">
        <shape>
            <gradient android:endColor="@color/steel_blue"  android:gradientRadius="50"
                android:startColor="@color/blue" android:angle="270" android:type="radial" />
               
            <stroke android:width="1dp" android:color="@color/lightblue" />
            <corners android:radius="5dp" />
            <padding android:left="1dp" android:top="20dp"
                android:right="1dp" android:bottom="20dp" />
        </shape>
    </item>
   

</selector>

First item is for non-selected tab and second for selected. In selected tab we are using radial gradient with start color and end color. In non-selected tab we are using linear gradient with start color, center color and end color and angle as 270. Angle can be 90, 180, and 270. Other values for angle will crash the program. Center color is optional.


You can get more info about custom shapes in this android tutorial http://developer.android.com/guide/topics/resources/drawable-resource.html
At the end, my tabs look like this. Well don't bother about color combination, I know I am not so good in that.



The gradient type can be linear, radial or sweep - linear is default. For selected tab I am using radial gradient. 

Notice one more thing here, I am defining two shapes - one for selected and another for not selected - using selector. If you want to use this for button you can use android:state_pressed and android:state_focused and define different shapes for these.
Look at another example where I am defining different drawable pngs for different states
<?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="false"
         android:drawable="@drawable/lightbtn" >
        
    </item>
    <item android:state_pressed="true"
        android:drawable="@drawable/darkbtn">
        
    </item> 
    

</selector>

This xml file is stored as mybutton.xml in /res/drawable-hdpi and I use the following line in my layout file
----
----
<Button
    android:layout_height="wrap_content"                 android:layout_width="wrap_content"
    android:id="@+id/okbutton"
    android:layout_gravity="center_horizontal"
    android:layout_marginTop="50dp"
    android:background="@drawable/mybutton">
    </Button>

I have lightbtn.png and darkbtn.png in my /res/drawable-hdpi . Now when I touch the button darkbtn is displayed else lightbtn is displayed

Thursday, March 10, 2011

How to access sqlite table from emulator

You can see the contents of text files by exporting it from emulator, but what about sqlite tables? You can use sqlite3 as explained below.
You need to access the adb shell first.
If you are using Linux system, it is simple enough. Just give the command

    adb shell

But for windows xp system, the path might not be properly set. If that is the case, go to the folder where android sdk is installed

If android sdk is installed in f:\android-sdk-windows, then go there and then goto subdirectory tools in that.
Now give the command

     adb shell

Next you need to go to directory which has your sqlite database. For that you use command
     cd /data/data
     cd com.pkg.pkg1

Here com.pkg.pkg1 must be replaced by your packagename of android project.

     cd databases
     dir

At this point, dir must show you the name of your database file. If your database name is mydb, then to open it using sqlite, give the command

    sqlite3 mydb

Now you can use any sql command like select, insert , update etc.

     .tables
     select * from expenses;

Do not forget to end your sql commands with a semicolon.


Be careful if you give a wrong database name, instead of prompting sqlite just shows empty db.
Here is a list of some other useful commands
.schema table
Gives the create statement for that table so you will come to know the columns of the table

.headers on
Shows your select statement with column name headers.

.quit
Terminate sqlite

.help

To obtain a list of sqlite3 commands you can use