Monthly Archives: June 2013

How to Install .apk File onto an Android Device

The Problem

I am new to the Android platform. At work, I need to side-load our app for testing. My device is an HTC one of 2012. At first, I installed and ran the HTC Sync Manager from my MacBook Pro with hope that it could help me, but after half an hour, I gave up: I copied the .apk file to the file section, sync, then check the phone: I could not find that .apk file anywhere. It could be me, but for the life of me, I could not find a way to copy the file in question onto the device. There must be a better way.

My Solution

As I stated before, the problem is with me being a novice. However, I did spend a good half an hour googling for solutions to no avail. Finally, an idea came to me: what if I can transfer the file from my Mac to the HTC One via HTTP? With that though, I opened up a terminal session, cd to the directory where my .apk file is, and issued the following command:

python -m SimpleHTTPServer

That command created an impromptu web server to serve all the files within the current directory. From the HTC One, I fired up a web browser and jumped to my server: haiv-mac1.local:8000 and expected to see the directory listing. However, I could not connect to my Mac at all. Frustrated, I tried again and again, prepending http:// to the address, check my spelling, knelt down and prayed… But nothing worked. I tried the same address using my iPhone and it works. So the problem was with the Android device. Finally, I was able to connect using my Mac’s IP address. How I love Android!

Once I downloaded the file, it was a simple matter of tapping the Downloads icon, find my file, and tap on it to install.

Conclusion

I like the Android platform for giving me the ability to side-load apps, which is great for testing. However, the process could be simpler. Veteran Android users and developers might laugh hearing this story, but it is no joke to me. Until I gain enough expertise, I’ll stay with my trusty iPhone.

Tcl: A Custom For Loop

The Problem

I often need to loop through a list of items and need both the index position, and the item itself. Typically:

set names {John Paul George Ringo}
set i 0
foreach name $names {
    puts "$i - $name"
    incr i
} 

Output:

0 - John
1 - Paul
2 - George
3 - Ringo

Initial Solution

Since I frequently do this, I decided to implement my own loop and call it for_item_index for lack of creativity. Here is my loop and a short code segment to test it:

proc for_index_item {index item iterable body } {
    uplevel 1 set $index 0
    foreach x $iterable {
        uplevel 1 set $item $x
        uplevel 1 $body
        uplevel 1 incr $index
    }
}

# Test it
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "$i - $name"
}

I have tested it with break, and continue and found my new loop performs as expected. My concern is the excessive use of uplevel command in the code.

Here are my own review of my code:

  • Excessive use of uplevel – I don’t know what to do about it. If you have an idea, please send it my way.
  • The index always starts at zero. There are times when I want it to start at 1 or some other values. To add that feature, I will probably introduce another parameter, startValue
  • Likewise, the index always get incremented by 1. The user might want to increment it by a different values such as 2, or –1 to count backward. Again, introducing another parameter, step might help, but at this point, the loop is getting complicated.

Revised Solution

Shortly after the initial solution, I posted it on StackExchange’s CodeReview site. While waiting for comments, I started to revise the initial solution to include the start- and increment values. Here is the revised solution and code snippets to demonstrate:

proc for_index_item {indexexpr itemvar iterable body} {
    # Break down indexexpr
    set step 1
    set start 0
    if {[llength $indexexpr] == 3} {
        set step [lindex $indexexpr 2]
    }
    if {[llength $indexexpr] >= 2} {
        set start [lindex $indexexpr 1]
    }
    upvar 1 [lindex $indexexpr 0] index
    set index $start

    upvar 1 $itemvar item

    # Actual loop
    foreach item $iterable {
        uplevel 1 $body
        incr index $step
    }
}

#
# Test
#

puts "\nDefault, start with 0"
set names {John Paul George Ringo}
for_index_item i name $names {
    puts "  $i - $name"
}

puts "\nStarts from 1"
set names {John Paul George Ringo}
for_index_item {i 1} name $names {
    puts "  $i - $name"
}

puts "\nWith start value and increment"
set names {John Paul George Ringo}
for_index_item {i 110 10} name $names {
    puts "  $i - $name"
}

Output:

Default, start with 0
  0 - John
  1 - Paul
  2 - George
  3 - Ringo

Starts from 1
  1 - John
  2 - Paul
  3 - George
  4 - Ringo

With start value and increment
  110 - John
  120 - Paul
  130 - George
  140 - Ringo

A few comments:

  • I took in a suggestion and used upvar instead of uplevel, which makes the logic a little cleanner.
  • Half of my code is now devoted to parsing
  • The word index is miss-leading: it has nothing to do with the index as in a list index. It is just part of a sequence of numbers. In the future, I might rename it to remove confusion.

Let the Mac Speak for Me

The Problem

I often lose my voice temporarily due to allergy. During that time, my main mode of communication is a notepad, or the electronic equivalent: Zen Brush. I was looking for a solution that can convert what I type into spoken words.

The Solution

Since I am using Mac both at home and at work, and Mac has the say command which is useful for this purpose; I decided to roll my own solution. It turned out that the solution is a very simple bash script, which I named speak4me.sh, which I saved in my ~/bin directory:

#!/bin/bash
while read line
do
    say -v Alex $line
done

To make the script executable, I issued the following command:

$ chmod +x ~/bin/speak4me.sh

Using speak4me.sh

To use speak4me.sh, from the terminal, issue the following command:

$ speak4me.sh

After that, start typing your message. As soon as you hit the return key, the script will “say” what you type. You can keep on typing and hitting return. To end the script, just type Ctrl+C.

Discussion

The script is very simple, pragmatic and free from bells and whistles, but it works the way I like it. The -v Alex part of the say command specifies a voice from Alex. OS X comes with a few voices which you can experiment with yourself. To list the voices your system has, issue the following command:

$ say -v ?
Agnes               en_US    # Isn't it nice to have a computer that will talk to you?
Albert              en_US    #  I have a frog in my throat. No, I mean a real frog!
Alex                en_US    # Most people recognize me by my voice.
Bad News            en_US    # The light you see at the end of the tunnel is the headlamp of a fast approaching train.
Bahh                en_US    # Do not pull the wool over my eyes.
Bells               en_US    # Time flies when you are having fun.
Boing               en_US    # Spring has sprung, fall has fell, winter's here and it's colder than usual.
Bruce               en_US    # I sure like being inside this fancy computer
Bubbles             en_US    # Pull the plug! I'm drowning!
Cellos              en_US    # Doo da doo da dum dee dee doodly doo dum dum dum doo da doo da doo da doo da doo da doo da doo
Deranged            en_US    # I need to go on a really long vacation.
Fred                en_US    # I sure like being inside this fancy computer
Good News           en_US    # Congratulations you just won the sweepstakes and you don't have to pay income tax again.
Hysterical          en_US    # Please stop tickling me!
Junior              en_US    # My favorite food is pizza.
Kathy               en_US    # Isn't it nice to have a computer that will talk to you?
Pipe Organ          en_US    # We must rejoice in this morbid voice.
Princess            en_US    # When I grow up I'm going to be a scientist.
Ralph               en_US    # The sum of the squares of the legs of a right triangle is equal to the square of the hypotenuse.
Trinoids            en_US    # We cannot communicate with these carbon units.
Vicki               en_US    # Isn't it nice to have a computer that will talk to you?
Victoria            en_US    # Isn't it nice to have a computer that will talk to you?
Whisper             en_US    # Pssssst, hey you, Yeah you, Who do ya think I'm talking to, the mouse?
Zarvox              en_US    # That looks like a peaceful planet.

Python: Making Complex Regular Expression Easier to Read

In my last post, I shared a way to created regular expression with embedded comments for the Tcl scripting language. It turns out that Python also offers similar feature.

The Problem

I often need to deal with complex regular expression while scripting in Python. The problem is, the expression syntax is terse, cryptic and hard to understand and debug. There must be a better way to deal with regular expression, a way to add comments would be nice.

The Solution

As with my last post, I will use the same example: fishing out email addresses from a chunk of text. Below is the Python counterpart of my previous solution:

import re

if __name__ == '__main__':
    test_data = '''
            This is a bunch of text
            within it, there are some emails such as foo@bar.com
            or one@two.three.net
            What about mixed case: John.Doe@services.company.ws...
            Let see if we can extract them out
            '''
    email_pattern = r'''
            # The part before the @
            [a-z0-9._%-]+

            # The ampersand itself
            @

            # The domain, not including the last dot
            [a-z0-9.-]+

            # The last dot
            \.

            # The top-level domain (TLD), which ranges from 
            # 2 to 4 characters
            [a-z]{2,4}
            '''
    print 'START'
    result = re.findall(email_pattern, 
            test_data, 
            re.IGNORECASE|re.VERBOSE)
    print '\n'.join(result)
    print 'END'

The output:

START
foo@bar.com
one@two.three.net
John.Doe@services.company.ws
END

Conclusion

With the re.VERBOSE flag, I can embed white spaces and comments in the regular expression, making it easier to read and understand.

A Less AWKward For Loop

When writing an AWK script, many people who come from C background write the for loop for accessing an array like this:

for (i=1; i <= length(myarray); i++) {
    # Do something with myarray[i]
}

There is nothing wrong the the above code: it gets the job done. However, the loop feel less AWK-like and a little … AWKward. Besides, the above pattern does not work with arrays whose indices are strings, not number. A better way to write the same for loop is:

for (i in myarray) {
    # Do something with myarray[i]
}

So, stop being AWKward and start coding your for loop the AWK way.

Tcl: Making Complex Regular Expression Easier to Read

The Problem

I often need to deal with complex regular expression while scripting in Tcl (or other languages, for that matter.) The problem is, the expression syntax is terse, cryptic and hard to understand and debug. There must be a better way to deal with regular expression, a way to add comments would be nice.

For example, below is the expression to extract email addresses:

set email_pattern {[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}}

Below is some code to demonstrate the use of this pattern to extract email from a block of text:

set test_data {
	This is a bunch of text
	within it, there are some emails such as foo@bar.com
	or one@two.three.net
	What about mixed case: John.Doe@services.company.ws...
	Let see if we can extract them out
}

set email_pattern {[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}}

puts "START"
set result [regexp -inline -all -nocase $email_pattern $test_data]
puts [join $result "\n"]
puts "END"

The output:

START
foo@bar.com
one@two.three.net
John.Doe@services.company.ws
END

While this code gets the job done, the lack of document on the regular expression makes it hard to debug the code. Don’t you wish you could include comments to make it easier to read?

The Solutions

My first instinct was to break up the regular expression into parts, then glue them together:

set pre_ampersand {[a-z0-9._%-]+}
set domain {[a-z0-9.-]+}
set tld {\.[a-z]{2,4}}
set email_pattern ""
append email_pattern $pre_ampersand @ $domain $tld

That’s better, the code is now self-documented and I have broken up the long expression into manageable pieces. The drawback is I have to use so many variables to accomplish my goal.

After digging into the Tcl’s regex documentation, I discovered the -expanded flag which will do what I want: It allows me to add white space and comments to the regular expression. Now the code becomes:

set test_data {
	This is a bunch of text
	within it, there are some emails such as foo@bar.com
	or one@two.three.net
	What about mixed case: John.Doe@services.company.ws...
	Let see if we can extract them out
}

set email_pattern {
	# The part before the @
	[a-z0-9._%-]+

	# The ampersand itself
	@

	# The domain, not including the last dot
	[a-z0-9.-]+

	# The last dot
	\.

	# The top-level domain (TLD), which ranges from 2 to 4 characters
	[a-z]{2,4}
}

puts "START"
set result [regexp -expanded -inline -all -nocase $email_pattern $test_data]
puts [join $result "\n"]
puts "END"

The above code accomplished the same goal as before. While it is longer it is better documented and easier to understand and debug. For those who code in Python, a similar feature exists: it is called the re.VERBOSE flag.