Make Eclipse Clean and Rebuild an Android .apk When any Project File is Changed

November 23, 2011
Tags: , ,

Eclipse’s default behavior for an Android project seems to ignore changes to project files that aren’t handled by a Builder.

For example, an Eclipse project might have a text file with configuration data referenced in Project Explorer. By default, Eclipse will NOT rebuild and upload the .apk file upon modifying that file and Running or Debugging the project. Instead, the console shows:

[2011-11-21 21:51:25 - MyProject] Application already deployed. No need to reinstall.

This is also the default behavior of Eclipse with the Android Native Development Kit (NDK). Although running ndk-build creates new native C or C++ libraries, Eclipse does not rebuild and upload the .apk file upon using Run and Debug functions. Instead, it launches the old .apk file that already exists on the Android device.

The simplest solution is to enable the following option: Window | Preferences | General | Workspace | Refresh automatically. This causes Eclipse to automatically detect a change to a file referenced in Eclipse Project Explorer and Cleans, rebuilds and uploads the .apk file appropriately. I found I need to wait just a few seconds after saving the file before pressing F11 to launch Eclipse’s debugger.

This is saving me a lot of time in the build cycle.

DiggDeliciousFacebookTwitterStumbleUponGoogle ReaderShare
0

The Foolproof Guide to Troubleshooting Anything

October 6, 2011

My work is fast paced. I show up at your business with two or three days to help you improve your situation as promised. If we encounter a technical roadblock, it’s imperative for you and me to resolve it before I leave for my next assignment.

Good troubleshooting skills are vastly useful. No matter whose fault a problem is, if it’s in the way of doing what you’re paid to do, you might not be paid.

I work in the computer software industry and that is where my expertise lies. However, the principles of troubleshooting are abstract and universal.

“One bite at a time…one bite at a time”

A few times now, I’ve been asked, “How the hell do you know all this stuff?” To me, this question sounds ridiculous. Trust that I’m hating myself appropriately for using a cliché so early in this post, but I promise it will be the only one: How the hell do you eat an elephant? One bite at a time, of course.

You have probably witnessed an expert or “master” working on a problem. The master is on, and is so all the time. The master seems to know exactly how to approach every troublesome situation relating to his or her craft. The master either knows the solution to the trouble or knows where to look next to find it (which ultimately leads him to the solution or to another expert who can help). These skills, along with experience, are what separate mere competence from mastery.

Although they are likely smart people, there’s not necessarily anything intellectually spectacular about masters. Additionally, an individual that is a master on one subject is generally a novice on countless others. The point is, mastery of a skill comes from consistently exercising an efficient, honed application of logic.

When something isn’t working the way you think it should, the best way out of this situation is to break the system into manageable pieces. Don’t stare gloomily at the problem in hopes of intimidating a solution to present itself. Go to work. The process should be like a montage from a Rocky movie, except in real time and less exciting to the average onlooker.

Two immediate effects result from applying this technique:

  1. In breaking the system into smaller parts, your problem will take on an appearance of solve-ability rather than instill hopelessness.  Keeps your moral up, in other words!
  2. Once you’ve identified multiple pieces of the system, you can analyze each of them in turn. Then, it’s much more likely you’ll isolate a single non-working part of the system. Fix it and you’ve succeeded.

Some people do this more quickly and mentally than others. Speed and precision come with experience. The basic procedure is always the same, though.

Dissection of the system

Step 1: Determine the requirements that yield the desired result

Every troubleshooting scenario is the same in at least two ways:

  1. There are one or more general requirements that must be fulfilled to yield a desired result.
  2. There are one or more issues that stand in the way of the requirements working to cause the desired result, instead causing an undesirable actual result.

The desired result is usually pretty easy to identify. It’s the point at which you consider the trouble to be over. You don’t have to consult with anyone else about the desired result; the fact that it’s not happening is the reason you’re troubleshooting in the first place.

The actual result is also easy to identify. It’s simply what happens instead of the desired result. Note, and this is very important, that the actual result is not the direct opposite of the desired result. It is what specifically happens instead of the desired result. It’s very important to distinguish between the two, because the latter likely contains information about the issues, where the former does not.

The general requirements may or may not be immediately obvious, depending on your experience. An internet search is a decent place to get started. Google isn’t omnipotent, however; you’ll get better results asking someone instead. Just pay attention to what that person says; you’ll need to know it again and again.

Also, if there’s a manual or documentation, familiarize yourself with it.

Dissection, Step 1, Example 1: Car

  • Desired result: Your car starts when you turn the key in the ignition.
  • Actual result: Your car is completely silent when you turn the key in the ignition (not “your car doesn’t start”).
  • How to find general requirements? Search internet for “how does a car start” or ask anyone who’s worked on a car.
  • General requirements: Spark plug generates a spark. Spark must ignite fuel in engine. Engine must compress fuel.

Dissection, Step 1, Example 2: Computer

  • Desired result: Your computer connects to the World Wide Web.
  • Actual result: Your computer displays an error message when you launch your web browser (not “your computer doesn’t connect to the World Wide Web”).
  • How to find general requirements? Search internet for “how does a computer connect to cable internet” or call anyone who works on computers.
  • General requirements: Web browser communicates with network adapter, network adapter connects to home router, home router connects to cable modem, cable modem connects to ISP.

Step 2: Find and diagnose unfulfilled requirements

At this point, you have a basic idea of what it takes to make The Thing you’re using do What You Want. If all the general requirements are met, the desired result will happen. Now you have to analyze each of the general requirements and determine which one or ones are not being met.

Depending on your level of expertise and the complexity of the system, this might be a mental exercise, a written one, or both. I like to make big headers on paper for general requirements and then scrawl detailed notes between them.

Find and diagnose, Step 2, Example 1: Car

“Okay, I’ve determined the general requirements are spark, fuel, and compression. I also found info on testing each of these requirements. Where should I begin?

Hmm, I don’t have a compression test kit, so let’s skip that requirement for now. Fuel…I filled the car with gas yesterday, so there’s fuel in the tank. Is it getting to the engine? I discovered through my research that a working fuel pump should make a whirring noise when I turn the key. But my actual result confirms there’s no noise. Maybe there’s a problem with fuel delivery. Spark…I discovered I can do a spark test quickly with only a screwdriver, so let’s try it. Yep, there’s a spark.

Spark: check. Fuel: in question. Compression: probably fine, but I’ll get my neighbor to pick up a compression test kit on the way home. Now to start investigating at the fuel pump.”

Find and diagnose, Step 2, Example 2: Computer

“Okay, I’ve determined the general requirements are connectivity between my computer, the router, the cable modem, and the ISP. Where should I begin?

I skimmed the manual for the cable modem, and it said a solid, non-blinking light means the modem is connected to the ISP. That’s the case, so I think the cable modem and ISP are okay. The router status lights are okay, and Steve’s computer is connected to the router and his internet is working fine. Therefore, I conclude the requirement not being fulfilled is connectivity between my computer and the router.

Cable modem and ISP: check. Wireless router: check. Computer’s connection to router: in question. I’ll investigate that. The actual result is the web browser is giving me an error message, so I’ll do a Google search for that message from Steve’s computer.”

You should understand from the examples why it’s important to identify the actual result correctly. It may contain key information about which requirement(s) aren’t being met.

Step 3: Repeat steps 1-2 on the unfulfilled requirements

So far, we’ve demonstrated with two examples how to identify the desired result, actual result, and general requirements of a troubleshooting scenario. We’ve also demonstrated how to isolate unfulfilled requirements that are preventing the desired result.

Notice, however, that neither of the example problems have actually been solved. So far, these are crappy examples of troubleshooting, you might think. In fact, though, these are excellent examples of how real-world troubleshooting actually works.

Troubleshooting is an iterative process. What that means is you must now apply the same steps to a different set of information drawn from the results of your last attempt.

In the example with the car, we ended being pretty confident there was a fuel pump delivery problem. Therefore, our next iteration involves determining the general requirements to yield the desired result (fuel delivery) and then finding and diagnosing any unfulfilled requirements.

In the example with the computer, we ended with confidence that the problem was with the computer itself rather than the wireless router, cable modem or ISP. Therefore, our next iteration involves determining the general requirements to properly connect the computer to the wireless router (desired result).

The number of iterations required depends on the complexity of the problem, of course. Some sources of trouble are just more elusive and rare than others. At this point, however, you should have a clear idea of how you can use the procedure above to “close in” and eliminate unfulfilled requirements and yield your desired result.

Now Go to Work

Yes, that’s all there is to it. With the information above, you are poised to learn how to fix anything.

The most valuable and rewarding thing about experience with a system is the reusability of the knowledge gained from working with that system. Reusability of knowledge is the reason you see masters working faster than others. Additionally, mastery of the principles of troubleshooting makes learning new things easier and easier. Yes, the more things you learn to do, the easier it is to learn to do additional things.

The masters are the ones who remember and connect all the conclusions they draw from careful application of the troubleshooting process.

DiggDeliciousFacebookTwitterStumbleUponGoogle ReaderShare
0

Use Postfix to send email through Microsoft Exchange server

December 25, 2010

Last week, we installed the excellent Request Tracker (RT) 3.8.8 software on a Debian 5 Linux system for evaluation. RT is a powerful open source issue tracking system.

When tickets are updated, RT must send email messages to the relevant people. Since our organization’s email is handled by a hosted Microsoft Exchange server, we needed our Linux machine to automatically log in and send outgoing emails through our MS Exchange server.

There are many applications for this technique. For example, a system administrator might use maintenance scripts to send logs to interested parties.

The procedure below is a “cheat sheet” for this configuration. It is meant to show the steps as briefly as possible, with a minimal but complete explanation. It also notes any troubleshooting steps we followed.

Throughout this tutorial, personal information is obfuscated using xX and yY. Output is in bold text.

Install Postfix

The first step toward handling email on a Linux machine is to select a Mail Transfer Agent (MTA) or “mailer”. We use Postfix for our implementation.

First, install Postfix, which automatically removes Debian’s default MTA, exim4. Also install the modules necessary for SASL authentication:

debian:~# apt-get install postfix libsasl2-modules

After installation is complete, Postfix will prompt for some information.

General type of mail configuration: Internet site
System mail name: mydomain.com

System mail name is the default domain name from which email will originate (the “from” address, without a user prefix).

Optional: Send email manually via SMTP/telnet to make sure this works

Now that Postfix is installed, make sure we can use our Exchange server. Manually test ESMTP on our server over telnet. ESMTP is the protocol used by our Exchange server.

debian:~# telnet mail.mydomain.com 25

where mail.mydomain.com is the Exchange server’s fully qualified domain name or IP address, followed by its SMTP port.

Trying xXx.xXx.xXx.xx...
Connected to mail.mydomain.com.
Escape character is '^]'.
220 incoming-imf1.mydomain.com Microsoft ESMTP MAIL Service, Version: 6.0.3790.3959 ready at Thu, 23 Dec 2010 18:08:28 -0500

Say ehllo to the Exchange server from our email domain:

EHLO mydomain.com
250-incoming-imf1.mydomain.com Hello [xX.xXx.xX.xX]
250-TURN
250-SIZE 104857600
250-ETRN
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-8bitmime
250-BINARYMIME
250-CHUNKING
250-VRFY
250-X-EXPS GSSAPI NTLM LOGIN
250-X-EXPS=LOGIN
250-AUTH GSSAPI NTLM LOGIN
250-AUTH=LOGIN
250-X-LINK2STATE
250-XEXCH50
250 OK

Our Postfix configuration will use the AUTH LOGIN mechanism, so send that command here:

AUTH LOGIN

The following Base64 output decodes to “Username:”. Enter our username encoded in Base64 (do that here):

334 VXNlcm5hbWU6
xXxXxXxXxX

The server returns “Password:”. Enter our Base64-encoded password:

334 UGFzc3dvcmQ6
yYyYyYyYyY
235 2.7.0 Authentication successful.

We see this message and don’t hear any dolphins crying, so we’re clear to proceed as planned. Use MAIL FROM and RCPT TO commands to specify the “from” and “to” email addresses, respectively:

MAIL FROM:fritz@mydomain.com
250 2.1.0 fritz@mydomain.com....Sender OK
RCPT TO:fmahnke@yYyY.com
250 2.1.5 fmahnke@yYyY.com

Notice the “to” email address for the test is on a different domain. This is important, since mail servers may have different authentication requirements for same-domain and cross-domain email. Carefully compose a test message:

DATA
354 Start mail input; end with <CRLF>.<CRLF>
It was quite the dark and stormy afternoon.
omgwtfbbq
.

250 2.6.0 Queued mail for delivery
.
QUIT
221 2.0.0 incoming-imf1.mydomain.com Service closing transmission channel
Connection closed by foreign host.

By all accounts, this was successful, so open a beer and check the fmahnke@yYyY.com email account for a new message. If it’s there, we know we can control our mail server from this machine.

Postfix configuration

Postfix needs credentials to login to the server and send email. Add the mail server domain name and username:password (NOT encoded in Base64) of our user to /etc/postfix/sasl_passwd:

mail.mydomain.com fritz@mydomain.com:secretpassword

Secure the password file from the peons:

debian:~# chown root:root /etc/postfix/sasl_passwd
debian:~# chmod 600 /etc/postfix/sasl_passwd

Postfix does not work with plain text files. Update the password database (must be done whenever /etc/postfix/sasl_passwd is modified):

debian:~# postmap hash:/etc/postfix/sasl_passwd

Under no circumstances should root@mydomain.com be the reply to address for an email originating from our machine (this account does not exist on our hosted Exchange server), so we map (masquerade) it to an interested party. Add this and any other desired mappings to /etc/postfix/generic:

root@mydomain.com fritz@mydomain.com

Update the address maps database (must be done whenever /etc/postfix/generic is modified):

debian:~# postmap /etc/postfix/generic

Modify the main Postfix configuration file, aptly named /etc/postfix/main.cf:

# enable SASL for authentication
smtp_sasl_auth_enable = yes
# force AUTH LOGIN mechanism. Else Postfix might try something else
smtp_sasl_mechanism_filter = login
# Override Postfix default disallowing of plaintext AUTH LOGIN
smtp_sasl_security_options =
# use our password database for authentication
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
# map machine email addresses to internet addresses
smtp_generic_maps = hash:/etc/postfix/generic
# send mail through our Exchange ESMTP server
relayhost = mail.mydomain.com

We must restart Postfix when we make changes.

debian:~# postfix reload

It should now work perfectly. Let’s test.

debian:~# sendmail fmahnke@yYyY.com
Employees must wash hands before returning to work.
.

Postfix writes its output to syslog. Check the status of our message:

debian:~# tail /var/log/syslog

Dec 24 05:21:37 debian postfix/qmgr[4748]: EBE246625F: from=, size=307, nrcpt=1 (queue active)
Dec 24 05:21:38 debian postfix/smtp[4816]: EBE246625F: to=, relay=mail.mydomain.com[144.202.247.20]:25, delay=3.9, delays=2.1/0.03/1.2/0.55, dsn=2.6.0, status=sent (250 2.6.0 <20101224112136.EBE246625F@debian.localdomain> Queued mail for delivery)

Check fmahnke@yYyY.com for the new message. Is it there? Sweet. Postfix is configured successfully.

Further reading:

XFOR: Telnet to Port 25 to Test SMTP Communication
Troubleshooting SMTP Authentication using Telnet
Introduction to Microsoft Exchange Server 2003 – SMTP Auth Login

DiggDeliciousFacebookTwitterStumbleUponGoogle ReaderShare
3

Colored BASH shell prompt to easily identify SSH sessions

December 24, 2010
Tags: , , ,

My administrative machine is a laptop running Ubuntu. I use SSH to access my headless servers and test machines, so I wanted a way to make it more obvious whether any given terminal window is on the local machine or connected to a remote one.

I found this post, which explains how to change the color of the BASH shell prompt.

To change the color of the shell prompt permanently, modify the SSH user’s /home/.bashrc:

#export PS1='\h:\w\$ '
export PS1="\e[0;31m[\u@\h \W]\$ \e[m "

where 0;31 is the desired color code. Making the change in a user’s .bashrc causes the colored prompt to be applied upon every login.

DiggDeliciousFacebookTwitterStumbleUponGoogle ReaderShare
0

Customizing Firefox’s search bar to ban useless web sites from Google

March 10, 2010
Tags: ,

I love Firefox’s tabbed browsing and search bar for collecting research and solving problems. It’s so fast: press CTRL+T to open a new tab, press CTRL+K to switch focus to the search bar, type the search keywords, and press ENTER.

What I don’t like is when I eagerly click a promising search result and am greeted by something similar to the following:

experts-exchange.com preview page

experts-exchange.com preview page

experts-exchange.com has caused me quite a bit of browsing letdown over the past couple years of technical research. They may have the most relevant result to all my queries as promised, but I am not going to sign up for the experts-exchange.com service to find out. I can remove these annoying search results by adding the following operator to my Google search queries: -site:experts-exchange.com. In fact, any web site can be excluded from Google’s search results by adding this operator in the form -site:badwebsite.com.

The -site operator is effective, but it is impractical to add this operator to every Google search we perform. Luckily, we can customize Firefox’s search bar plugin to automate this procedure and banish experts-exchange.com from all Google searches through eternity. Here’s the procedure.

Create a copy of %systemdrive%\Program Files\Mozilla Firefox\searchplugins\google.xml in the same folder and save it under a different name (e.g. google_ban_experts_exchange.xml). Open the new .xml file with your favorite text editor.

Modify the content of the ShortName element. This value determines how Firefox will name the new search plugin:

<ShortName>Google (no EE)</ShortName>

Secondly, find the following line:

<Param name="q" value="{searchTerms}"/>

The value attribute specifies what is sent to the search engine URL when the search plugin is used. {searchTerms} is a variable that expands to the text entered in the Firefox search bar. Modify this line as follows:

<Param name="q" value="{searchTerms}+-site%3Aexperts-exchange.com"/>

Note that, for Google, a space character between keywords or operators must be changed to a plus sign (+) when used inside the Param element. Also, the colon character must be percent-encoded, so it is changed to %3A.

Save the changes to the .xml file and restart Firefox, if necessary. Click the dropdown button to the left of the Firefox search bar; Google (no EE) is now available from the list. After performing a search using this new plugin, the results screen should show Firefox automatically adds -site:experts-exchange.com before performing the search.

I picked on experts-exchange.com in this post (and rightly so, since they've dashed my hopes for at-my-fingertips content so many times), but this trick can be used to customize searches using other operators as well. For example, one could build a search plugin that constrains results to a range of dates or that searches only for files of a certain type.

DiggDeliciousFacebookTwitterStumbleUponGoogle ReaderShare
0