Site Sponsors:
Java Threads in Android 

Android Threads


Those looking to port threads to Google's Android Operating System are often frustrated: While the classic thread classes are there, using threads in your application can cause some pretty tough-to-debug problems.

Indeed, while 'googling around the 'net, one is often told not to use threads. We are told that using a Handler is better.

While using handlers is sage advice for supporting small lightweight duties, sometimes you just want to use a little thread, anyway. Indeed, as processors, battery, and RAM become less and less of an issue in our pockets, many lean-and-mean anti-thread discussions sound much like the CGA -v- VGA display-support discussions we had at Informix while writing Wingz in the early 1990's. When all is said and done, it seems that - at the moment - most technical limitations simply fade away...

The best reason why most use an honest-to-goodenss thread on android is to do heavier number crunching. By doing computer-intensive work away from the main user experience, we all know that things simply work better. (Even in user interfaces it seems, nobody likes a jerk! ;-)

Thread Hangups


Typically, one is crunching data for a reason: To eventually display something interesting. For this reason, one of the first head-scratchers we encounter when using a thread in an Android App is how it can completely trash an application. In fact, the most certain way to lock your 'App occurs whenever another Android Thread touches the GUI API in any way, shape, or form.

Consider the following:


import java.util.Timer;
import java.util.TimerTask;

public class TimeTicker extends TimerTask {

Date date = new Date();
Date dateLast = new Date();
private boolean bRunning = false;

@Override
public void run() {
dateLast = date;
date = DateX.GetToday();
if (bRunning) {
mainActivity.setDialogResult(DateX.FormatRfc822Date(date), iId);
}
}
}


In this example, our standard Java TimerTask implementation is running every second (not heavy-weight, I know - but it is the classical "hello world" example in the timer world.) Whenever we want it to send a timer event, it will do so using the setDialogResult() of mainActivity.

All well and good.

Once inside of mainActivity, we can easily update a few basic elements. When we try to invalidate the drawable surface to show the update however (a GUI function) at the time of this writing, things will go boom:


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_MARK:
{
this.vtBanner.sText = sResult;
this.invalidate(); // BOOM!
}
break;
// ...
}
}


Maddeningly, until we understand Android's thread model, the reason things suddenly go south is not readily apparent. Indeed, if we use an Android Dialog Activity, things work just fine!

By way of example, the following View.OnClickListener will update the GUI via that same setDialogResult() member function, just as easy as expected:


public void onClick(View arg0) {
dialog.bOkay = bSetValue;
this.dialog.dismiss();
if (bSetValue) {
Editable eString = dialog.editTextName.getText();
mainActivity.setDialogResult(eString.toString(), iId);
}
}


It can even Toast!


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_NEXT:
{
// Toast t = Toast.makeText(this.getContext(), sResult, 600);
// t.show();
this.vtBanner.sText = sResult;
this.invalidate(); // Works Fine!
}
break;
}
}


Why can one listener-laden Activity manage the Canvas, while even the lightest Thread, cannot?

One Thread to Draw Them All


Believe it or not, the reason why one class is blessed and another is cursed is simple: In the above example, even though the code is written as part of the main Activity class, our TimerTask is still effectively executing the code. Unfortunately, the timer running the TimerTask is not part of the main activity thread. It is another thread.

The Dialog, however, is a completely different case. Because Android Dialogs are Views, they will all share the same, common, execution thread.

Insidious, no? ( Surely knowledge is power !-)

Fortunately, the Android Framework 'wizards foresaw our dilemma: By allowing us to enqueue certain whole-life methods on-the-stack, the problem of having a non-GUI thread manage a GUI-Thread's ... uh ... gui ... is very well supported, indeed:


public void setDialogResult(String sResult, int iId) {
switch (iId) {
case BUTTON_MARK:
{
this.vtBanner.sText = sResult;
this.postInvalidate(); // Another Thread = NOT thread safe!
}
break;
case BUTTON_NEXT:
{
this.vtBanner.sText = sResult;
this.invalidate(); // Another Activity = Same GUI Thread
}
break;
}
}


-We simply need to be sure that non-GUI threads never use GUI access routines directly. -It is a thread safety thing. (i.e. Even relatively speaking, providing millions of synchronizing gatekeeper operations would slow everything down. The logic here is that it is better to make the developers work a little, than to make the computer work-a-lot. (yea, that logic sounds a lot like another ancient (1970!) pro-assembly-language argument to be sure... but we like Java, C++, and C# anyway. Computers got a whole lot faster, cheaper, and better!))

Want to discuss the slow death of java.util.Vector, anyone? (--me neither :)

Executive Summary


To conclude, when it comes to using Java's classic timers & threads, we can indeed do so ... even on Android - with relative impunity. Nevertheless, when doing so we must remember to always manage those secondary threads carefully. No mater what mechanism we may cobble-together to update Android's display, we must always be sure to access that Android UI only from the main user-interface-thread!

For more information on threading and thread-related issues, you can read more under the painless threading topic on the Android Developer's Site.

[ view entry ] ( 3584 views )   |  permalink
Cosmos Screen Saver 

Reminiscance


Ah, for the days of Carl Sagan - when the threat of national socialism, global warming, and removing funding from the arts and sciences seemed to be a problem for a republic far, far, away...

While this note has absolutely nothing to do with the late, great cosmic scientist (you know - the one who made billions & billions, only to become affectionately know to Mac developers as "BHA"?), the household conversion from Microsoft Windows to Linux brought such thoughts to mind when passers-by began to comment on this marvelously-named, free screensaver.

NASA


The pictures included with the Cosmos screen-saver are wonderful. So too are the pictures circulated by the National Aeronautics and Space Administration. While bringing both together seems like a natural thing to do, there is simply no documentation on how to do this.

So here it is:

Enjoying Billions & Billions of Pictures


First, consider signing-up to the NASA News Services (last seen at the NASA Web Site, note that we can also browse & download stellar pictures from there directly, too.)

Save your favorites to a common location. Any folder / directory will do.

Next, set the permissions of the Cosmos folder to something like

sudo chmod 777 /usr/share/backgrounds/cosmos

(did I ever mention that we switched from Centos to Ubuntu? ...If you are not on a similar, then feel free to drop the sudo.)

Then locate & open the Cosmos configuration file (you might even want to put a link to /usr/share/backgrounds/cosmos on your desktop)

file:///usr/share/backgrounds/cosmos/background-1.xml

(aka /usr/share/backgrounds/cosmos/background-1.xml)

Finally, edit the XML to include the picture(s) you would like to display.

Cosmos XML


While adding too many files will certainly be a painstaking process, here is what a new entry for background-1.xml might look like (apparently Cosmos scripts can be timed - feel free to experiment with creating additional xml file names):

<transition>
<duration>5.0</duration>
<from>/usr/share/backgrounds/cosmos/cloud.jpg</from>
<to>/home/profnagy/515307main_PIA13449_full.jpg</to>
</transition>

Also, when adding a new picture to Cosmos, note that we are editing a chain of pictures. To insert the latest cosmic work-of-art, merely (1) locate where in the chain you want your new picture to appear, then (2) add an entry in-between (or at the beginning or end) of the Cosmos picture chain.

Once you have given yourself access to the cosmos directory, you can store your pictures there, too. Just dropping your 'pix there will allow them to be randomly displayed.

Conclusion


Of course, in addition to snaps of the galaxy's breathtaking beauty, we can add other types of pictures to Cosmos, too. --Just be sure that the pix from your last family reunion are out-of-this-world.


Enjoy!

[ view entry ] ( 3844 views )   |  permalink  |  related link
Incrementally Backing Up Changes to a USB Drive in Linux 

Saving Changes Anywhere?


Whenever we want to back up a Linux file system to a FAT / FAT32 file system, strange things can happen!

The need was to help us incrementally, and recursively, back-up file changes made during the past few days to a huge USB drive. -Since FAT partitions do not have all of that POSIX info, we were getting tired of waiting while absolutely everything was being copied over - even things that had not changed.

Unless you want to re-format the FAT partition to use NTFS (or EXT`n`), then there are two techniques here. The first technique also creates an on-line archive. The second works a lot like Mr. Bill's xcopy.

Technique 1: Coding It


Because the following script uses tar rather than cp, your file dates and time stamps will be preserved. Even ctime, mtime, or atime ... all the time!


#!/bin/bash

file_name="`basename $0`"
days='7'
file_tar="$HOME/$file_name.tar"
file_tar_list="$HOME/$file_name.found"

source="$1"
dest="$2"

echo 'Started at' `date` ", looking for deltas within $days days"

echo 'Source = '$source', Destination = '$dest
echo 'TAR file is ' $file_tar
echo 'FIND file is ' $file_tar_list

echo ' '
# echo 'Cleanup started at ' `date`
# $(find $source -name *.class -print -exec rm '{}' \; )
# $(find $dest -name *.class -print -exec rm '{}' \; )

echo ' '
echo 'Tar-up started at ' `date` ' from ' $source
pushd . > /dev/null
cd $source
find . -type f -mtime -$days -print > $file_tar_list
tar cvf $file_tar -T $file_tar_list
popd > /dev/null

echo ' '
echo 'Un-tar started at ' `date` ' to ' $dest
tar xvf $file_tar -C $dest

echo ' '
echo 'Completed at ' `date`



Since I have been writing a lot of Java this decade, I included a way to remove all of those pesky .class files. Just remove my # comments before those first find statements if you have a similar need.

Calling It


Once you copy the above into a file name (such as _io_sync.sh in the below,) all you need to do next is to call it. The _io_sync.sh script expects a pair of folders on its command-line:


#!/bin/bash
clear

source='/d_drive'
dest='/media/PATRIOT/d_drive'

file_name="`basename $0`.rpt"

./_io_sync.sh $source $dest | tee $file_name


Designed to be reflective, you can even swap the source and destination file around with impunity:


#!/bin/bash
clear

dest='/d_drive'
source='/media/PATRIOT/d_drive'

file_name="`basename $0`.rpt"

./_io_sync.sh $source $dest | tee $file_name


Of course, it is of no importance if we use the above on CentOS, Ubuntu, Slackware, or DSL. -This backup routine will work the same wherever a console / terminal / command-line / secure shell / or other script-running shell interface is available.

Left-Overs


Perfect for pen-drives, hard disks, or other mountable media, this script will leave a copy of the .tar file on your hard-drive in your home directory ($HOME) after all is said and done. A copy of the report file will also be placed right next to the script for your perusal & retroactive peace-of-mind, as well.

Technique 2: Preservations


If you do not want to have an on-line archive laying around, then you can just use:


#!/bin/bash
for arg in "/my_folder1" "/my_folder2"
do
cp -r -u -v --preserve $arg "./"
done


Simply copy & paste the above into a file, mark that file as executable, then modify and copy the script to where you would like the backup to store YOUR folders - like on a USB drive.

Best of all, note that running the operation repeatedly will only copy the 'deltas' (changes,) not everything else.

Conclusions


Clearly both techniques are superset operations: The only potential down-side is that previously deleted files will still be left hanging-around your backups. So if you want verbatim archives, then either delete the backup folders from time to time, else copy the tar file, as described earlier, to your backup device.

Finally, note that the above operations also work the same on NTFS, as well as on all EXT-n, partitions.

Enjoy!

R.A. Nagy


NOTE: If your are backing up to a POSIX file system and want to keep a log, then you might want to also consider this article.


Before any backup strategy however, don't forget to watch for, as well as reclaim any Zombies!

[ view entry ] ( 2561 views )   |  permalink  |  related link

<<First <Back | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Next> Last>>