This is not a complete tutorial on how to use AlarmManager and NotificationManager, but a simple sample.
The scenario is I want to have a alarm set to certain time. When it goes off, it show notification icon on status bar. When click on the notification, it will start an activity.
1. Create the BroadcastReceiver
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
NotificationManager mNM;
mNM = (NotificationManager)context.getSystemService(context.NOTIFICATION_SERVICE);
// Set the icon, scrolling text and timestamp
Notification notification = new Notification(R.drawable.icon, "Test Alarm",
System.currentTimeMillis());
// The PendingIntent to launch our activity if the user selects this notification
PendingIntent contentIntent = PendingIntent.getActivity(context, 0, new Intent(context, TestActivity.class), 0);
// Set the info for the views that show in the notification panel.
notification.setLatestEventInfo(context, context.getText(R.string.alarm_service_label), "This is a Test Alarm", contentIntent);
// Send the notification.
// We use a layout id because it is a unique number. We use it later to cancel.
mNM.notify(R.string.alarm_service_label, notification);
}
}
2. Add Receiver to Manifest.xml
<receiver android:process=":remote" android:name="AlarmReceiver"></receiver>
3. Set the alarm
public class AlarmService {
private Context context;
private PendingIntent mAlarmSender;
public AlarmService(Context context) {
this.context = context;
mAlarmSender = PendingIntent.getBroadcast(context, 0, new Intent(context, AlarmReceiver.class), 0);
}
public void startAlarm(){
//Set the alarm to 10 seconds from now
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, 10);
long firstTime = c.getTimeInMillis();
// Schedule the alarm!
AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, firstTime, mAlarmSender);
}
}
1. Create tabs
TabHost tabHost = getTabHost(); // The activity TabHost
TabHost.TabSpec spec; // Resusable TabSpec for each tab
Intent intent; // Reusable Intent for each tab
// Create an Intent to launch an Activity for the tab (to be reused)
intent = new Intent().setClass(this, TaskActivity.class);
// Initialize a TabSpec for each tab and add it to the TabHost
spec = tabHost.newTabSpec("task").setIndicator("Task", null).setContent(intent);
tabHost.addTab(spec); // Do the same for the other tabs
intent = new Intent().setClass(this, CalendarActivity.class);
spec = tabHost.newTabSpec("calendar").setIndicator("Calendar", null).setContent(intent);
tabHost.addTab(spec);
2. Customize tabs
TabHost tabHost = getTabHost();
LinearLayout linearLayout = (LinearLayout) tabHost.getChildAt(0);
TabWidget tw = (TabWidget) linearLayout .getChildAt(0);
RelativeLayoutfirstTabLayout = (RelativeLayout) tw.getChildAt(0);
//First tab
TextViewtabHeader = (TextView) firstTabLayout .getChildAt(1);
tabHeader .setTextSize(18); //Change text size
tabHost.getTabWidget().getChildAt(0).getLayoutParams().height = 36;
//Change first tab header height
firstTabLayout.setBackgroundResource(R.drawable.group_background_overdue);
tabHeader.setText("Tab page 1");
Sort by simple type property
1. Implement the Comparable interface
public class Item implements Comparable<Item> {
…
}
2. Implement the compareTo method.
@Override
public int compareTo(Item another) {
//Compare the name
return this.name.compareTo(another.name);
}
3. Call sort
List<Item> items = ..
items.sort();
Sort by user defined property
1. Create a new class
import java.util.Comparator;
public class ItemCompareByLocation implements Comparator<Item>{
@Override
public int compare(Item arg0, Item arg1) {
return arg0.getLocation().compareTo(arg1.getLocation());
}
}
2. Call sort
Collections.sort(items, new ItemCompareByLocation());
Create style.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="DetailTextView" parent="@android:style/TextAppearance">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">14sp</item>
<item name="android:textStyle">bold</item>
</style>
<style name="DateTimeButton" parent="@android:style/Widget.Button">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:gravity">left|center_vertical</item>
<item name="android:textSize">19sp</item>
</style>
</resources>
Use it in layout
<TextView android:id="@+id/TextView01" android:text="What" style="@style/DetailTextView" />
Simple toast:
Context context = getApplicationContext();
CharSequence text = "Hello toast!";
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(context, text, duration);
toast.show();
Customized toast:
LayoutInflater inflater;
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.detail_toast,
(ViewGroup)arg0.findViewById(R.id.toast_layout_root));
TextView taskTextView = (TextView)
layout.findViewById(R.id.taskTextView);
taskTextView.setText(task.getName());
TextView detailTextView = (TextView)
layout.findViewById(R.id.detailTextView);
detailTextView.setText(sb.toString());
Toast toast = new Toast(context.getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
Travel Phrase - French helps you to learn and practice basic survival phrase for travel. Not only it has more than 120 useful phrases, but it also allows you to edit and add your own. It uses Text-To-Speech technology to provide pronunciation for each phrase. To help you review the phrases, you may choose to hide the phrases in one language, then try to remember the phrase in the other language. The paid version app doesn't require internet connection and can be used offline.




User Guide
Pronunciation
To listen to the pronunciation of a phrase, tap the French phrase or the pronunciation part. You will need to have Text-To-Speech Engline installed and enabled. Pico TTS is a typical TTS engine to install.
Review Mode
After learning the phrases, you may press "Menu"->"Hide English"/"Hide French" to hide the English or French phrases so you can test if you remember its meaning in the other language. Tap the phrase to reveal the answer.
New Category
Press "Menu"->"New Category" to add new categories.
Edit/Delete Category
To edit/delete a category, long press the category and choose "Edit"/"Delete" from the popup menu.
New Phrase
Long press on a category, then choose "New Phrase" from the popup menu to add new phrase.
If you don't have a French keyboard, the app provides a small keyboard for entering special characters in French.
Edit/Delete Phrase
To edit/delete a phrase, long press the phrase and choose "Edit"/"Delete" from the popup menu.
Sort
You may sort the phrases alphabetically by press "Menu"-"More"->"Sort Alphabetically". You can also press the space right in front of each phrase, then drag/drop to re-order them.
Search
To find an item, click on "Menu"->"More"->"Search". A text box and "Find Next" button will show up at the bottom of the screen. Enter the word you search for and tap on "Find Next".
Settings
In paid version, go to "Menu"->"Settings". Users can also customize the background and text colors.You can also choose to not display the pronunciation.
Edit List On Desktop
The phrase file is saved in XML format on SD card under \sdcard\travelphrase\ folder. You may upload them to your desktop computer for easy editing. Just make sure you follow the exact format.
There are some icons and xmls under C:\Android\android-sdk-windows-1.6_r1\platforms\android-1.5(or other version)\data\res\drawable
To use different icons for standard control, we can copy the xml file and icons used in the xml to our own \drawable folder and set it in the layout xml
1) Grab the checkbox_background.xml and checkbox.xml from above folder and copy to the drawable folder in my project
2) Copy all the PNG files for the checkbox to the drawable folder in my project
3) Change the layout to use the checkbox (In my case, it is a CheckedTextView)
android:checkMark="@drawable/checkbox"

Recently our two applications on Android Market kept reporting error “java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap…”. If you look at the stack trace, there is no trace of our code. Below is one of the stack trace:
java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@4478a900
at android.graphics.Canvas.throwIfRecycled(Canvas.java:955)
at android.graphics.Canvas.drawBitmap(Canvas.java:1044)
at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:323)
at android.widget.ImageView.onDraw(ImageView.java:842)
at android.view.View.draw(View.java:6740)
at android.view.ViewRoot.draw(ViewRoot.java:1407)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1163)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:4627)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:521)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
at dalvik.system.NativeStart.main(Native Method)
After searching around the Internet, I found some clues. It has something to do with the call of bitmap.recycle(). Some people suggest to remove all the calls to bitmap.recycle() and let the garbage collector to do the job. So I tried this solution and updated the Packing List application. I will give it a day or two to see if it settles the issue.
Chore Checklist helps you to manage chores at home or other places. It records chores' completion date and calculate next due date based on your preference. You can also set reminder for each chore.
It comes with a pre-loaded check list which has routines, such as "Daily Routine", "Weekly Routine", "Monthly Routine" and etc. You may edit them or add new routine/chores.




Recent release notes:
5/31/2011 V1.4.9
- Improve performance when check off a chore
- Fix bug in checking off all chores in a routine
- Allow customizing text size in widget
5/27/2011 V1.4.8
- Fix date parsing issue for non-English locale
- Fix issue with alarms when there are more than one daily routines
- Allow moving to SD card (NOTE: if you choose to move to SD card, you will not be able to use widgets. If later you changed your mind, you will have to uninstall and reinstall the app)
- Other minor bug fixes
4/15/2011 V1.4.7
- Fix "Force Close" issue when choose to show chores overdue and due today only
4/11/2011 V1.4.6
- Add menu option to display chores overdue and due today only.
- Add setting to allow users to disable widget customization if they have issue loading the widget
4/8/2011 V1.4.5
- Add widget customization back (Full version only)
- Note: widget customization may not work on some devices. If it doesn't work for you, please contact us. We will either fix it or refund your money.
4/7/2011 V1.4.4
- Removed the change for widget customization since it causing "Problem Loading Widget" issue on some devices
4/4/2011 V1.4.3
- Fixed issue in resetting progress
- Allow changing background and text colors of the widget(Full version only)
3/28/2011 V1.4.2
- Fixed "Force Close" issue when set reminder in routine
- Other minor bug fixes
3/25/2010 V1.4.1
- Added date/time to notification
- Added toast for alarm date/time
- Added preference setting for changing the background and text colors for all the routines and chores (full version only)
- Added better color picker
- Fixed widget display issue
- Fixed notification issue
- Other bug fixes
3/17/2011 V1.3.4
3/16/2011 V1.3.3
- Add display options to allow user to choose which routine to be displayed in the widget and which routine to be always expanded in the list
- Allow carriage return in notes
- Do not pop-up date picker when complete one-time chores
- Fix bugs in auto resetting progress
- Fix display issue when screen orientation changes
- Fix bugs in multiple notification and clear notification bar when a chore is completed
- Other bug fixes
User Guide
Add Routine
To add new routines, click on "Menu"->"New Routine". You may enter frequency which is how often you want to do the chores under this routine. For example, you can set the routine as every 2 days, every 2 weeks, every 3 months and etc.
Edit/Delete Routine
To edit/delete a routine, press and hold it's name. Choose "Edit"/"Delete" from the popup menu. You may also set the completion date, due date and reminder for all the existing chores on a routine.
Add Chore
To add new chore under a routine, press and hold a routine, then select "New Chore" from pop-up menu.
Edit/Delete Chore
To edit/delete a chore, press and hold it's name. Choose "Edit"/"Delete" from the popup menu. You may edit the name, notes, progress and etc.
If you entered notes for a chore, an information icon will be displayed on the list view. To get a quick view of the notes, you may touch the icon, a toast window will show up with the notes.
If the progress is set, a progress bar will also show on the list view.
Complete/Skip Chore
When check off a daily chore, the completion date will be set to today. When check off non-daily chore, a date selection window will popup to have you enter completion date. If the chore has a reminder, it will be re-calculated based on the next due date.
If a chore has passed its due date, you may choose to skip the chore instead of competing it. Tap and hold the chore. Choose "Skip" from popup menu. It will re-calculate the next due date without changing the completion date.
Day Patterns For Daily Routine(Full Version Only)
For chores under daily routine, you can now set which day of the week the chores need to be done. For example, you can choose only the weekdays or weekends, etc.
The day pattern will be displayed on the list view when it is set.
Set Reminder
For chores under daily routine, you can set the reminder to specific time of a day. It will automatically repeat daily. For other routines, the reminder will be set to relatively to the due date or specific time on the due date. It will not repeat until you complete/skip the chore. A clock icon will show on the list view when a chore has reminder set up.
Re-Order Chores/Routines
To re-order the chores under a routine, touch the left side of the check box and drag the item. You may also drag it to another routine. To re-order the routines, first collapse the list, then drag and drop by touching the left side of a routine.
You can sort the chores alphabetically or by due date.
Automatic Reset
Daily routine will be reset everyday. That is if you checked some items today, they will be unchecked tomorrow automatically.
Other routines' checkboxes will be unchecked half way towards the next due date.
Settings(Full Version Only)
There are several settings under Menu->More->Settings
You can change how it calculates the next due date. It defaults to use previous due date. That is if you have a weekly chore set to be done on every Sunday. The next due date will always be on Sunday. You may choose to calculate base on the completion date. So if you finished it on Tuesday, the next due date will be next Tuesday, not Sunday.
You can also change the starting day of a week if you are using day patterns for daily routine. It defaults to Sunday.
There are settings for default alarm ringtone and background colors.
Widget
This application has one widget in lite version and three different size widget in full version.
Edit List On Desktop
The list is in XML format under \sdcard\chorechecklist\. You may upload it to desktop and edit it using a text editor. Please make sure to only edit the name/notes and follow the exact format. If for some reason, the file is corrupted, you may delete it so the application can re-load the pre-defined list.
Set Layout_weight to greater than 0


When I use anything other than textview in a listview, the context menu stop working. Now to have a check box in a list view, I have to use CheckedTextView. But the text in CheckedTextView appears on the left side of the checkbox. I don’t know how to change it, so I use a CheckedTextView with no text and a TextView.
<CheckedTextView android:id="@+id/categoryCheckedTextView"
android:layout_width="wrap_content"
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
android:layout_height="wrap_content"
android:clickable="true">
</CheckedTextView>
AlertDialog alertDialog;
alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Packing List");
alertDialog.setMessage("Could not find the file.");
alertDialog.show();
Use KEYPAD_7 or KEYPAD_9 on you desktop. You need to turn off your Num Lock.
To dynamically change the background color, use myView.setBackgroundResource(R.color.my_color) instead myView.setBackgroundColor(R.color.my_color)
How to align text in text view?
When trying to align the text to the right in text , set the “layout_gravity” to right doesn’t work. Need to set “gravity” to right.
PackageInfo pi;
String versionName = "";
try {
pi = getPackageManager().getPackageInfo(getPackageName(), 0);
versionName = pi.versionName;
} catch (NameNotFoundException e) {
e.printStackTrace();
}
TextView itemTextView = (TextView)itemView.findViewById(R.id.itemTextView);
itemTextView.setText(item.getItem() + "(" + Integer.toString(item.getQuantity()) + ")");
if (item.isChecked())
itemTextView.setPaintFlags(itemTextView.getPaintFlags() | Paint.STRIKE_THRU_TEXT_FLAG);
else
itemTextView.setPaintFlags(itemTextView.getPaintFlags() & ~Paint.STRIKE_THRU_TEXT_FLAG);
How to show HTML content in Android?
You can use WebView to display HTML content in Android.
WebView webView = (WebView)helpView.findViewById(R.id.helpWebView);
String data = fileUtitlity.readFileToString(R.raw.help);
webView.loadData(data, "text/html", "UTF-8");
How to loop through Hashtable in Java?
Hashtable<DateTime, String> alarms = new Hashtable<DateTime, String>();
Enumeration<DateTime> keys = alarms.keys();
while( keys.hasMoreElements() ) {
DateTime alarmTime = keys.nextElement();
String value = alarms.get(alarmTime);
alarmService.startAlarm(alarmTime, value);
}
To remove a view from the layout, use View.GONE. View.Invisible will save the space
taskProgressBar.setVisibility(View.GONE);
taskTextView.setBackgroundResource(android.R.color.transparent);
How to set system color?
routineTextView.setTextColor(context.getResources().getColor(android.R.color.primary_text_dark));
How to set color to gradient color?
Define group_background_overdue.xml in drawable folder:
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="4dp" />
<gradient
android:angle="270"
android:startColor="#F6A59D"
android:endColor="#F41A0B" />
</shape>
Then set the color using the following code:
groupTextView.setBackgroundResource(R.drawable.group_background_overdue);
How to read file to String and how to convert bytes to string?
public String readFileToString(int resId){
InputStream ins = context.getResources().openRawResource(resId);
int size;
String file = "";
try {
size = ins.available();
// Read the entire resource into a local byte buffer.
byte[] buffer = new byte[size];
ins.read(buffer);
file = new String(buffer, 0, size, "UTF8");
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
How to set Android default icon for menu items?
android:icon="@android:drawable/ic_menu_preferences"