Android development primer: Working with Sliding Drawers in Android – Part II

In the first part, I showed you how to use a basic Sliding Drawer in Android. In this post I’ll show you how to make your Sliding Drawers fancier by changing the handle image when the Sliding Drawers is open and when it is closed. The complete source code is at the bottom.

  • Save the two images from here and here. Name them help_handle_open and help_handle_close respectively.
  • Navigate to <yourprojectname> -> res -> drawable-ldpi/mdpi/hdpi/xhdpi/xxhdpi.
  • Right click and select New -> Android XML file. Choose selector from the Root Element list. Name the xml file help_handle_customizer.
  • Paste the following code in it.
    <selector
    	xmlns:android="http://schemas.android.com/apk/res/android">
    	<item
    		android:state_pressed="true"
    		android:drawable="@drawable/help_handle_open" />
    	<item
    		android:state_focused="true"
    		android:drawable="@drawable/help_handle_close" />
    	<item
    		android:drawable="@drawable/help_handle_open" />
    </selector>
  • In the ImageView which you have for your SlidingDrawer Handle change the @android:src attribute value to @drawable/help_handle_customizer.

Now, when you run it on the emulator or an actual device, you can see the handle images changing based on whether the Sliding Drawer is open or close.

COMPLETE SOURCE CODE

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="bottom"
    android:background="#D0D0D0"
    android:paddingBottom="0dp">

    <SlidingDrawer
        android:id="@+id/slidingDrawer"
        android:handle="@+id/drawerHandle"
        android:content="@+id/contentLayout"
        android:layout_width="wrap_content"
        android:layout_height="200dip"
        android:orientation="horizontal"
        android:layout_gravity="center_vertical">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/handlerl"
            android:paddingBottom="0dp">

	        <ImageView
	            android:id="@+id/drawerHandle"
	            android:src="@drawable/help_handle_customizer"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_alignParentRight="true" >
        	</ImageView>

        </RelativeLayout>

        <ScrollView
            android:id="@+id/contentLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

        <RelativeLayout
            android:id="@+id/inner"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#B0B0B0">

            <TextView
		        android:id="@+id/helptv1"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:text="Your first text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv2"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv1"
		        android:text="Your second text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv3"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv2"
		        android:text="Your third text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv4"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv3"
		        android:text="Your fourth text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

        </RelativeLayout>
        </ScrollView>

    </SlidingDrawer>
</FrameLayout>

A Simple Server

The task is to construct a simple server which just passes a string to the client.

Client/server describes the relationship between two computer programs in which one program, the client, makes a service request from another program, the server, which fulfills the request. Although the client/server idea can be used by programs within a single computer, it is a more important idea in a network.
A server runs on a specific computer and has a socket that is bound to a specific port number. The server just waits, listening to the socket for a client to make a connection request.
InputStream and OutputStream are used to transfer of data between server and client.

java.net includes Socket and ServerSocket classes.
java.io includes DataOutputStream and DataInputStream classes.

    Server-

[java]
import java.io.*;
import java.net.*;

public class server {

public static void main(String[] args) {
try{
ServerSocket s=new ServerSocket(1254); //same port number
Socket s1=s.accept(); //accepts the connection
OutputStream stout=s1.getOutputStream();
DataOutputStream dos=new DataOutputStream(stout);
dos.writeUTF(“HELLO WORLD”);
dos.close();
s1.close();
}
catch(Exception e)
{System.out.println(“”+e);}

}

}
[/java]

    Client-

[java]
import java.io.*;
import java.net.*;

public class client {
public static void main(String[] args) {
try{
Socket s= new Socket(“localhost”,1254);//localhost or any other IP
InputStream sin=s.getInputStream();
DataInputStream din=new DataInputStream(sin);
String str=new String(din.readUTF());
System.out.println(“”+str);
din.close();
sin.close();
s.close();
}
catch(Exception e)
{System.out.println(“”+e);}
}
}

[/java]


Note-

To check the programs,simultaneously run both the programs.

Subset Sum Problem (Part II)

Given a set of numbers,our task is to find the number of subsets that sum to a particular value.

Example-

Set of numbers- {1,3,2,5,4,9}
Sum=9

Subsets that sum to 9-

{1,3,5}
{5,4}
{9}
{3,2,4}

Thus,number of subsets that sum to 9 = 4.

Algorithm-

The idea is to find the number of possible sums with the current number.And its true that,there is exactly one way to bring sum to 0. At the beginning,we have only one number. We start from our target and subtract that number.If it is possible to get a sum of that number,then add it to the array element corresponding to the current number.

Code-

[cpp]

//N is the number of elements,
//sum is the given value,
//numbers[] contains the elements

int GetmNumberOfSubsets()
{
int dp[1000];
dp[0] = 1;
int currentSum =0;

for (int i = 0; i < N; i++)
{
currentSum += numbers[i];
for (int j = std::min(sum, currentSum); j >= numbers[i]; j–)
dp[j] += dp[j – numbers[i]];
}

return dp[sum];
}

[/cpp]

Note-

This algorithm works only for positive numbers.

Subset Sum Problem

Given a set of positive integers and a value sum,the task is to find if there is a subset with sum equal to the given value.

Example-

Given set of numbers- {3,34,4,12,5,2}

Sum=9.

The output will be ‘True’ because 4+5=9.

Algorithm-

The problem can be divided into two sub-problems-

1.By including the last element.
2.By excluding the last element.

Recursive Solution-

[cpp]
subsum(set, n, sum) = subsum(set, n-1, sum) //excluding the last element
|| subsum(arr, n-1, sum-set[n-1]) //including the last element

Base Cases:

subsum(set, n, sum) = false, if sum > 0 and n == 0
subsum(set, n, sum) = true, if sum == 0
[/cpp]

Code-

The above algorithm has exponential time complexity which can be converted to code having polynomial complexity using dynamic programming that is storing the intermediate results.

[cpp]

// Returns true if there is a subset of set[] with sum equal to given sum

bool isSubsetSum(int set[], int n, int sum)
{
// The value of subset[i][j] will be true if there is a subset of set[0..j-1]
// with sum equal to i
bool subset[sum+1][n+1];

// If sum is 0, then answer is true

for (int i = 0; i <= n; i++)
subset[0][i] = true;

// If sum is not 0 and set is empty, then answer is false

for (int i = 1; i <= sum; i++)
subset[i][0] = false;

// Fill the subset table in bottom up manner

for (int i = 1; i <= sum; i++)
{
for (int j = 1; j <= n; j++)
{
subset[i][j] = subset[i][j-1];
if (i >= set[j-1])
subset[i][j] = subset[i][j] || subset[i – set[j-1]][j-1];
}
}

return subset[sum][n];
}

[/cpp]

Android development primer: Working with Sliding Drawers in Android – Part I

You have to agree that the Sliding Drawer feature of Android is a pretty neat and handy tool to add some text – usually directions for use, help or other important details. Here’s what a Sliding Drawer looks like. The bold black lines are where some text will appear.

sd_close         open

Remember that a Sliding Drawer option is provided in the Palette in the Graphical Layout tab of any xml under the Composite section. However, I like to use a custom Sliding Drawer. It gives me absolute control over what my Sliding Drawer handle looks like, what orientation is it drawn into, what view I want it to have ( a custom one if needed) etc.

So below I provide a sample source code of how to code a Sliding Drawer into you layout. However, I would strongly recommend trying out the Sliding Drawer element from the Palette first, making a few changes to see how it reflects in the layout and then coming back here to look at the source code. This will help you get familiar with the xml.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_gravity="bottom"
    android:background="#D0D0D0"
    android:paddingBottom="0dp">

    <SlidingDrawer
        android:id="@+id/slidingDrawer"
        android:handle="@+id/drawerHandle"
        android:content="@+id/contentLayout"
        android:layout_width="wrap_content"
        android:layout_height="200dip"
        android:orientation="horizontal"
        android:layout_gravity="center_vertical">

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/handlerl"
            android:paddingBottom="0dp">

	        <ImageView
	            android:id="@+id/drawerHandle"
	            android:src="@drawable/help_handle_customizer"
	            android:layout_width="wrap_content"
	            android:layout_height="wrap_content"
	            android:layout_alignParentRight="true" >
        	</ImageView>

        </RelativeLayout>

        <ScrollView
            android:id="@+id/contentLayout"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

        <RelativeLayout
            android:id="@+id/inner"
            android:gravity="center"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#B0B0B0">

            <TextView
		        android:id="@+id/helptv1"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:text="Your first text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv2"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv1"
		        android:text="Your second text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv3"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv2"
		        android:text="Your third text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

            <TextView
		        android:id="@+id/helptv4"
		        android:layout_height="wrap_content"
		        android:layout_width="wrap_content"
		        android:layout_below="@+id/helptv3"
		        android:text="Your fourth text goes here."
		        android:paddingTop="5dp"
		        android:paddingBottom="5dp"
		        android:paddingLeft="5dp"
		        android:paddingRight="5dp"
		        android:textColor="#000000">
		    </TextView>

        </RelativeLayout>
        </ScrollView>

    </SlidingDrawer>
</FrameLayout>

There are a few things worth noting here :-

  • I have used a frame layout rather than Linear/Relative Layout. I particularly am much more comfortable with it while working with Sliding Drawers. You can read about Frame Layouts here.
  • The Sliding Drawer has attributes namely – android:handle and android:content. Notice that an ImageView is present that has the same id as the value for android:handle and a ScrollView with the same id as the value of android:content.
  • The android:handle attribute defines the handle of your sliding drawer.
  • The android:content attribute defines what your Sliding Drawer holds.
  • Notice that the ImageView which is the handle of the Sliding Drawer has an src attribute of @drawable/help_handle. Recollect from my earlier posts, to use an icon you must paste it in the drawable-ldpi/mdpi/hdpi/xhdpi/xxhdpi folder. I have an image by the name help_handle.png in my drawable folder.
  • Remember that this sort of reference is done in the xml. If you choose to refer to it from your Java code you must use R.drawable.<youriconname>.
  • Notice that the Sliding Drawer has a different handle (Image that works as a handle) when it is closed than from what it has when it is open. If you use the code I provided you with, you will not see this happening. I will discuss how to do it in detail in a later post. For now you can use the image here. Paste it in <eclipseworkspace>/<yourprojectname>/res/drawable-ldpi/mdpi/hdpi/xhdpi/xxhdpi.

Code it. Execute it on the emulator. Once it runs properly, start experimenting!! 🙂

Time Picker in Android

Just like Number Picker provides a neat way to select values from a given range, Android also provides a Time Picker tool. This, as the name suggest is used to pick time. Now, you can use the Time Picker the way you use Number Picker, but this post shows how to use it with the help of a TimePickerDialog.

  • Create a layout for an activity and insert a button. This button will trigger a dialog which will contain the TimePicker.
  • Define the button in the Java file.
  • Set the onClick() method for the button.[java]
    b.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
    showDialog(9999);
    }
    });
    [/java]

  • Create a new method onCreateDialog(). This comes into play when we call a Dialog to appear quite like the one we did above.
    [java]
    protected Dialog onCreateDialog(int id){
    switch(id){
    case 9999:
    return new TimePickerDialog(this, timePickerListener, Calendar.HOUR_OF_DAY, Calendar.MINUTE, false);
    }
    return null;
    }
    [/java]
  • We are setting the current time of the device as the default time every time the dialog appears.
  • Now, we need to define what happens when a time is selected. Here, I am just creating a Toast to show the selected time. Remember that you can do whatever you want. We will override the method onTimeSetListener()
    [java]
    private TimePickerDialog.OnTimeSetListener timePickerListener = new TimePickerDialog.OnTimeSetListener() {

    @Override
    public void onTimeSet(TimePicker view, int newhour, int newminute) {
    Toast.makeText(getApplicationContext(), newhour+”:”+newminute, Toast.LENGTH_LONG).show();
    }
    };
    [/java]

  • Save and run the application on an emulator or device.

Tpick1  Tpick2

Remember that the Time is always set in 24 Hour format.

COMPLETE SOURCE CODE

MainActivity.java

[java]
package com.nero.mysecondapp;

import java.util.Calendar;

import android.os.Bundle;
import android.app.Activity;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.TimePicker;
import android.widget.Toast;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) findViewById(R.id.button1);
b.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
showDialog(9999);
}
});
}

protected Dialog onCreateDialog(int id){
switch(id){
case 9999:
return new TimePickerDialog(this, timePickerListener, Calendar.HOUR_OF_DAY, Calendar.MINUTE, false);
}
return null;
}

private TimePickerDialog.OnTimeSetListener timePickerListener = new TimePickerDialog.OnTimeSetListener() {

@Override
public void onTimeSet(TimePicker view, int newhour, int newminute) {
Toast.makeText(getApplicationContext(), newhour+”:”+newminute, Toast.LENGTH_LONG).show();
}
};

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}

}

[/java]

Fixed: USB Drive Read Only in Ubuntu 13.04

Problem : USB disk/storage devices are auto loaded as Read Only in Ubuntu. When attempting write operation it gives the message like “Read only file system…”.

Reason: Unknown, looks like a bug in the usb disk handling in Ubuntu.

Fix: Run this command to remount as writable disk –

sudo mount -o remount,rw /media/<username>/<diskname>

(Pressing tab after /media/<username>/ can help you find the  disk to be provided.)

Number Picker in Android

Often times in our applications ,we are going to need to let the user choose numeric values. Of course we can design a custom Dialog box with an Edit Text and let the user type in the values. However, Android provides a very neat tool to do this with style and ease, the NumberPicker tool.

Complete Source Code is at the bottom.

  • Create a new Project and remember to set the minimum API version to at least 11 i.e. Honeycomb. This is because the support for the Number Picker has been introduces since API 11.
  • Create a layout for an activity. Drag and drop a Number Picker and a button from the palette on the left.
  • Switch over to the Java file and define the button and the Number Picker
    [java]
    Button b = (Button) findViewById(R.id.button1);
    final NumberPicker np = (NumberPicker) findViewById(R.id.numberPicker1);
    [/java]
  • Remember to make the Number Picker final.
  • Set the minimum and maximum values. This defines the range in which the user is supposed to enter the values.
    [java]
    np.setMinValue(1);
    np.setMaxValue(20);
    [/java]
  • Set the onClickListener() attribute for the button to display the value currently selected. We use the getValue() method for retrieving the current value.
  • Save it and execute in a device or an emulator that is running Android Honeycomb or higher.

NPick

COMPLETE SOURCE CODE

MainActivity.java

[java]
package com.nero.mysecondapp;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.NumberPicker;
import android.widget.Toast;

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button b = (Button) findViewById(R.id.button1);
final NumberPicker np = (NumberPicker) findViewById(R.id.numberPicker1);
np.setMinValue(1);
np.setMaxValue(20);
b.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), np.getValue()+””, Toast.LENGTH_SHORT).show();
}
});
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
[/java]

Alarm Manager in Android

AlarmManager as the name suggests is used to schedule actions in an Android system. Do not be misled by the name that it is used to schedule the alarms. It can be used to schedule alarms, notifications, broadcasts etc.

In this post I will show you how to schedule a notification from your application. We will make use of Alarm Manager through which we will send a broadcast, and a Broadcast Receiver using which we will receive the broadcast and use it to create a notification. Complete Source Code is at the bottom.

  • Set up a layout for your activity.
  • Switch to the Java file and create a global Alarm Manager object.
  • Define the object inside the onCreate() method.
    [java]
    am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    [/java]
  • Create a new method setAlarm(). Write the following lines inside it.
    [java]
    Intent intent = new Intent(this, AlarmReceiver.class);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    am.cancel(pendingIntent);
    GregorianCalendar alarmtime = new GregorianCalendar();
    alarmtime.set(GregorianCalendar.HOUR_OF_DAY, 6);
    alarmtime.set(GregorianCalendar.MINUTE, 0);
    alarmtime.set(GregorianCalendar.SECOND, 0);
    alarmtime.set(GregorianCalendar.MILLISECOND, 0);
    if(alarmtime.before(new GregorianCalendar()))alarmtime.add(GregorianCalendar.DAY_OF_MONTH, 1);
    am.set(AlarmManager.RTC_WAKEUP, alarmtime.getTimeInMillis(), pendingIntent);
    [/java]
  • Call this method inside the onCreate() method.
  • Create a new Java class that extends BroadcastReceiver class. Name it AlarmReceiver.java. Note that we have already used this name in the method setAlarm() above.
  • Inside the onReceive() method write the following lines. I will explain these line in a moment.
    [java]
    notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    Intent i = new Intent(context, Second.class);
    PendingIntent pi = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);

    AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    PendingIntent pi2 = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
    am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + AlarmManager.INTERVAL_DAY, pi2);

    CharSequence from = “Nero”;
    CharSequence message = “Test Notification”;
    notification = new Notification(R.drawable.ic_launcher,”Attention”,System.currentTimeMillis());
    notification.setLatestEventInfo(context, from, message, pi);
    notification.defaults|= Notification.DEFAULT_SOUND;
    notification.defaults|= Notification.DEFAULT_LIGHTS;
    notification.defaults|= Notification.DEFAULT_VIBRATE;
    notificationManager.notify(1, notification);
    return;
    [/java]

  • Add an entry in your manifest file
    <receiver android:name=".AlarmReceiver">
         <intent-filter>
            	<action android:name="android.intent.action.BOOT_COMPLETED"/>
         </intent-filter>
    </receiver>
  • Save it and execute it on a device or an emulator. Remember that we have scheduled a notification ar 6 am. You might need to change the date and time to see that the notification appears.

Understanding the Code

  • GregorianCalendar is a form of calendar present in the Android system. You can use Calendar too. Google it.
  • PendingIntent – It should be quite enough for you to know that we are creating an Intent that has to be fulfilled. The Broadcast receiver does that.
  • RTC_WAKEUP is used so that if your device is switched off, it starts up at the scheduled time and performs the action.
  • In the AlarmReceiver we are creating another PendingIntent that creates the intent for the alarm to fire the next day exactly at the same time.
  • ALARM_SERVICE is a service of Android system that we are calling inside the Broadcast Receiver.
  • FLAG_CANCEL_CURRENT is used to cancel any outstanding Intents. This is done so that at a time only a single Intent is active.
  • notification.defaults|= Notification.DEFAULT_SOUND – This provides for the Sound attributes of the notification. Same is the case with vibrate and Lights.

COMPLETE SOURCE CODE

AlarmReceiver.java

[java]
package com.nero.myfirstapp;

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

import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.util.Log;

public class AlarmReceiver extends BroadcastReceiver {

NotificationManager notificationManager;
Notification notification;
@Override
public void onReceive(Context context, Intent intent) {
notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
Intent i = new Intent(context, Second.class);
PendingIntent pi = PendingIntent.getActivity(context, 0, i, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
PendingIntent pi2 = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + AlarmManager.INTERVAL_DAY, pi2);

CharSequence from = “Nero”;
CharSequence message = “Test Notification”;
notification = new Notification(R.drawable.ic_launcher,”Attention”,System.currentTimeMillis());
notification.setLatestEventInfo(context, from, message, pi);
notification.defaults|= Notification.DEFAULT_SOUND;
notification.defaults|= Notification.DEFAULT_LIGHTS;
notification.defaults|= Notification.DEFAULT_VIBRATE;
notificationManager.notify(1, notification);
return;
}
}

[/java]

MainActivity.java

[java]
package com.nero.myfirstapp;

import java.util.ArrayList;
import java.util.GregorianCalendar;

import com.psyduck.myfirstapp.AlarmReceiver;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class Main extends Activity {
AlarmManager am;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
setAlarm();
}

public void setAlarm(){
Intent intent = new Intent(this, AlarmReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
am.cancel(pendingIntent);
GregorianCalendar alarmtime = new GregorianCalendar();
alarmtime.set(GregorianCalendar.HOUR_OF_DAY, 6);
alarmtime.set(GregorianCalendar.MINUTE, 0);
alarmtime.set(GregorianCalendar.SECOND, 0);
alarmtime.set(GregorianCalendar.MILLISECOND, 0);
if(alarmtime.before(new GregorianCalendar()))alarmtime.add(GregorianCalendar.DAY_OF_MONTH, 1);
am.set(AlarmManager.RTC_WAKEUP, alarmtime.getTimeInMillis(), pendingIntent);

}
}
[/java]

Custom Data Adapters with Checked List Views – Part II

In the last post, I showed you how to make the front end for the List View with check box using Custom Data Adapters. This post will deal with the coding of the custom Data Adapters. This one coupled with the last post, will complete the procedure.

The custom Data Adapter class is named Adapter.java and extends the ArrayAdapter<String> class. Quite obviously, this is because if you recall the lost post, you can see that I’ve used an ArrayList to populate the List View. Had I used a database, we could have used a CursorAdapter.

This code is complicated and hence I provide the explanations below.

Understanding the Code

  • A HashMap is a Java class that allows for key-value pair mapping. We are going to map each item with a boolean value that identifies if it is checked or unchecked.
  • We initialize all the items to unchecked in the constructor.
  • The toggle() function serves the purpose of checking or unchecking the item once it is clicked, depending on it’s previous state.
  • getCheckedItemPosition() serves the purpose of returning the indices of items that are checked.
  • getCheckedItems() serves the purpose of returning the items that are checked.
  • Remember that all these methods make use of the basic functions of the HashMap class of Java. If you face any difficulty understanding them, I suggest you read the Java HashMap documentation here.

CDA

COMPLETE SOURCE CODE

row_item.xml

<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/checkedtextview"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
    android:gravity="center_vertical"
    android:orientation="vertical"
    android:paddingBottom="10dip"
    android:paddingLeft="20dip"
    android:paddingRight="20dip"
    android:paddingTop="10dip"
    android:textColor="#000000" 
    
    android:onClick="toggle"
    >

</CheckedTextView>

activity_main.xml

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:background="#D0D0D0" >

    <Button
        android:id="@+id/addcourse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:text="Go" />
    
    <EditText
        android:id="@+id/coursenameet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:ems="10"
        android:layout_marginBottom="2dp"
        android:layout_marginTop="2dp"
        android:hint="Course Name" 
        android:inputType="textCapWords" >

    </EditText>
    
    <View
        android:id="@+id/divider"
        android:layout_width="match_parent"
        android:layout_height="3dp"
        android:layout_below="@+id/coursenameet"
        android:layout_marginBottom="5dp"
        android:layout_marginTop="5dp"
        android:background="@android:color/darker_gray" >
    </View>
    
    <TextView
        android:id="@+id/weekdaytv"
        android:layout_width="wrap_content"
		android:layout_height="wrap_content"
        android:layout_below="@+id/divider"
        android:layout_marginBottom="3dp"
        android:layout_marginTop="3dp"
        android:layout_centerHorizontal="true"
        android:text="Select weekdays for this Course" >
    </TextView>
    
    <RelativeLayout 
    	android:id="@+id/rlinner"
    	android:layout_width="match_parent"
    	android:layout_height="match_parent"
    	android:layout_centerVertical="true"
    	android:layout_centerHorizontal="true"  
    	android:layout_above="@+id/addcourse"
	    android:layout_below="@+id/weekdaytv">
	    
        <RelativeLayout 
	    	android:id="@+id/rlinnermost"
	    	android:layout_width="match_parent"
	    	android:layout_height="wrap_content"
	    	android:layout_centerVertical="true"
	    	android:layout_centerHorizontal="true" >
    	
		    <ListView
		        android:id="@+id/listView1"
		        android:layout_width="match_parent"
		        android:layout_height="wrap_content"
		        android:divider="#FFFFFF"
		    	android:dividerHeight="2dp" />
	    </RelativeLayout>
    	
	</RelativeLayout>

</RelativeLayout>

Adapter.java

[java]
package com.nero.myfirstapp;

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

import android.R.color;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import android.widget.Toast;

public class Adapter extends ArrayAdapter {

HashMap<Integer, Boolean> checked = new HashMap<Integer, Boolean>();
ArrayListweekdays;
Context context;
private int[] colors = new int[] { Color.parseColor(“#D0D0D0”), Color.parseColor(“#D8D8D8”) };
public Adapter(Context context, int resource, int textViewResourceId, ArrayList weekdays) {
super(context, resource, textViewResourceId, weekdays);
this.context=context;
this.weekdays=weekdays;
for(int i=0;i<weekdays.size();i++)checked.put(i, false);
}

public Adapter(Context context, int resource, int textViewResourceId, ArrayList weekdays, ArrayListoldweekdays) {
super(context, resource, textViewResourceId, weekdays);
this.context=context;
this.weekdays=weekdays;
for(int i=0;i<weekdays.size();i++)checked.put(i, false);
for(int i=0;i<oldweekdays.size();i++)checked.put(oldweekdays.get(i),true);
}

public void toggle(int position){
if(checked.get(position))checked.put(position, false);
else checked.put(position, true);
notifyDataSetChanged();
}

public ArrayList getCheckedItemPosition(){
ArrayListcheck = new ArrayList();
for(int i=0;i<checked.size();i++){
if(checked.get(i))check.add(i);
}
return check;
}

public ArrayList getCheckedItems(){
ArrayList check = new ArrayList();
for(int i=0;i<checked.size();i++){
if(checked.get(i))check.add(weekdays.get(i));
}
return check;
}

public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;

if(row == null){
LayoutInflater vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = vi.inflate(R.layout.row_item, null);
}

CheckedTextView checkedTextView = (CheckedTextView)row.findViewById(R.id.checkedtextview);
checkedTextView.setText(weekdays.get(position));
row.setBackgroundColor(colors[position % colors.length]);
return row;
}
}

[/java]

MainActivity.java

[java]
package com.nero.myfirstapp;

import java.util.ArrayList;

import android.app.Activity;
import android.database.Cursor;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Toast;

public class Main extends Activity {
ArrayList weekdays = new ArrayList();
ArrayList ret = new ArrayList();
ListView lv;
EditText coursename;
Button addcourse;
Adapter adapter;
String c;
long courseid;

public void initialize(){
weekdays.add(“Monday”);weekdays.add(“Tuesday”);weekdays.add(“Wednesday”);
weekdays.add(“Thursday”);weekdays.add(“Friday”);weekdays.add(“Saturday”);
}

public void getoldweekdays(long id){
ret.clear();
}

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ret.clear();
initialize();
lv = (ListView) findViewById(R.id.listView1);
coursename = (EditText) findViewById(R.id.coursenameet);
addcourse = (Button) findViewById(R.id.addcourse);
lv.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);

courseid = getIntent().getLongExtra(“courseid”, -1);
adapter = new Adapter(this, R.layout.row_item, R.id.checkedtextview, weekdays);
lv.setAdapter(adapter);
for(int i=0;i<ret.size();i++)lv.setItemChecked(ret.get(i), true);

lv.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
adapter.toggle(position);
}
});

addcourse.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
ArrayList checkeditem = adapter.getCheckedItems();
finish();
}
});
}
}
[/java]