Saturday, July 28, 2012

Book Report: Do More Faster

With the good weather and barren inbox (thanks Olympics!) I had time to plow through Do More Faster - a compendium of startup short stories by the founders of TechStars (Brad Feld and David Cohen).  Based on the Amazon sample I felt some trepidation as it seems like another useless brag-a-thon of successful start-ups.  However, based on rave reviews I plowed ahead.

The first half o the book was largely as expected - repetitive and cliche stories about listening to customers and making good products.  *yawn*  When I have real conversations with start-up junkies there is usually some secret sauce or unfair advantage they have/discovered/acquired to win in their market.  Its usually messy and held together with lots of hope and duct tape, but it's true.  I want to hear that - not 20 iterations of the obvious.

That being said, the last two chapters of the book on on legal issues and work-life balance made the slog worth while.  Stories told by many (but especially Brad Feld) unveiled some sinister issues almost any entrepreneur will face (equity battles and upset spouses) when going all in on a company.  These problems fall into the easy to prevent, but hard to solve category.  So, getting a good feel for the warning signs is absolutely critical (write a great vesting schedule and set up regular conversations with loved ones).  And the genuine, unique and heartfelt stories was a fresh infusion of life experience.  Wish they'd led with that!

Not one of my bibles, but worth a weekend read!
http://www.amazon.com/Do-More-Faster-TechStars-Accelerate/dp/0470929839

Thursday, July 26, 2012

Compress Pictures

PowerPoint has come to the point where it is a good enough image editing tool.  I can get 90% of my work done purely in PowerPoint+Office Pictures Manager.  It may sound crude, but it works well to produce images at a dizzying rate.

Typically I'll just create the image I want in PowerPoint using the built in screen clippings/shapes/filters and then select "Save as Picture" (part of the right click menu).  However, in a particular instance I found that all images were coming out half the desired height.  In PowerPoint they were perfectly square, but once saved the png/jpeg/gif output was squashed to a rectangle twice as wide as it was tall.

On a hunch I gave "Compress Pictures" a shot.  This is a tool that often does a big reset on the internal memory of PowerPoint.  And low and behold it worked!

Often the image you see on the screen is a very small fraction of what PowerPoint remembers about an image (the application remembers all cropping, largest resolutions, transformations etc). Its a good practice to keep your files small and keep PowerPoint running fast to use this command often to remove unnecessary assets.

Tuesday, July 24, 2012

Is your web server load high?

A couple weeks ago we were getting worried about CIMLS.com's server.  We were running a larger AWS instance and hitting 80%+ utilization on a continual basis. For a site of our size slinging simple HTML this is ridiculous.  So, what was the problem?

Crawlers....

The bots that work for various search engines were furiously indexing CIMLS.com resulting in almost 40% of our server load.  About half of that was Google.  While a worthy cause, we cut the load in half by lowering the crawl rate to .5 requests/second.  This hasn't significantly impacted the number of indexed pages (let alone organic traffic/rank).

Adjusting the Googlebot's crawl rate can be accomplished by visiting google.com/webmastertools >> configuration >> settings >> crawl rate.  We tried a number of options, but found .5->1 requests/second to be a sweet spot that got our pages indexed without tanking server performance for real users.

Another big surprise for us was that the bulk of the rest of the load wasn't from other crawlers like Bing or Yahoo!  Instead, two foreign crawlers Yandex (Russian) and Baidu (Chinese) were just hammering the system.  As we are a US oriented site, the traffic from these sources was negligible (and probably irrelevant).

We found that modifying the robots.txt was not effective (these bots just ignored it).  We had to use a RewriteCond to block the bot activity:


RewriteCond %{HTTP_USER_AGENT} Baiduspider [NC,OR]
RewriteCond %{HTTP_USER_AGENT} YandexBot
RewriteRule ^.*$ - [F]

Well, finally that did the trick - and removed nearly 20% of our server load overnight.  Phew!

Thursday, July 12, 2012

An Android Dialog before the Facebook Dialog

While I was writing an award screen for PollKarma I decided that users would like award screens.  The behavior occurs when a user answers x questions they got a pop-up with a cool image/message and an option to share on Facebook.  To get this done I made a custom dialog box that serves as a pre-cursor to the facebook dialog to provide some more context for the user and a nicer graphic (Facebook's is limited to the format of a wall post.

The simplest way to get this done is with a new xml file for the custom dialog box and to dump all the code in  the main execution file.

The Award.XML file is very simple.  Any good share dialog will need a big image along with a share and close button:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >
        <Button android:id="@+id/share" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:text="Share"></Button>
   
        <Button android:id="@+id/close" android:layout_width="wrap_content"
        android:layout_height="wrap_content" android:text="Close"></Button>
    <ImageView
    android:id="@+id/YourImage"
    android:src="@drawable/yourimage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
android:scaleType="fitXY"
></ImageView>
</LinearLayout>


Note the android:scaleType="fitXY" which auto-sizes your image to fill the layout and be big and pretty.

So, assuming you have a file named award.xml you can dump this code in the method triggered on any award event to provide a nice wrapper for a facebook wall share dialog:


final Dialog dialog = new Dialog(YourActivity.this);
dialog.setContentView(R.layout.award);
dialog.setTitle("This is my custom dialog box");
dialog.setCancelable(true);
Button closeBtn = (Button) dialog.findViewById(R.id.close);
closeBtn.setOnClickListener(new OnClickListener() {
@Override
    public void onClick(View v) {
        dialog.dismiss();
    }
});
Button shareBtn = (Button) dialog.findViewById(R.id.share);
shareBtn.setOnClickListener(new OnClickListener() {
@Override
      public void onClick(View v) {
      Bundle params = new Bundle();
      params.putString("caption", "yourcaption");
      params.putString("description", "yourdescription");
      params.putString("picture", "http://yoursite.com/images/yourimage.png");
      params.putString("name", "yourname");
      Utility.mFacebook.dialog(YourActivity.this, "feed", params, new DialogListener() {
          @Override
          public void onComplete(Bundle values) {
           dialog.dismiss();
          }
          @Override
           public void onFacebookError(FacebookError error) {}
          @Override
          public void onError(DialogError e) {}
          @Override
          public void onCancel() {}
      });
    }
});
dialog.show();
}

Sunday, July 8, 2012

Testing your Android Applications Internet Connection


Many droid apps rely on the internet to function.  My (soon to be released) PollKarma application relies on facebook for authentication, so I had to test this.  Googling the problem lead me to this solution:


public boolean isOnline() {
   
ConnectivityManager cm =
        (
ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

   
return cm.getActiveNetworkInfo() != null &&
       cm.getActiveNetworkInfo().isConnectedOrConnecting();
}

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />


This only does half the job.  Thankfully I was working on this at a starbucks.  Most public wifi these days will allow any device to connect, but requires a further action before connecting to the internet.  The above code really test the network connection (are you on Wifi) not internet connection (can you get data from the www). 

After some trial and error I came up with this solution:

public void initialize() throws IOException{URL url = new URL("http://yoursite.com");URLConnection connection = url.openConnection();try { HttpURLConnection httpConn = (HttpURLConnection) connection; httpConn.setRequestMethod("GET"); httpConn.connect();        //initialize your application here now that the connection is confirmed } catch (Exception e) {        //set up an alert dialog for graceful failure if no connection is available              e.printStackTrace(); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage( "No Connection.  Please logon to the Internet to continue.") .setCancelable(false) .setPositiveButton("Retry", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { try { initialize(); } catch (Exception ie) { ie.printStackTrace(); } } }) .setNegativeButton("Close", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { YOURCLASS.this.finish(); } }); AlertDialog alert = builder.create(); alert.show();}}


which is called from onCreate like so:

try{  initialize();}catch(Exception e){  e.printStackTrace();}

This functionality not only performs a test ensure the connections you really need are available, but it also provides the user with an elegant alternative if there is no connection. Quite a few steps better than the default hang on no connection!


Simple Android Debug Procedure


Identify WHERE the issue is happening

  1. Look at the logcat error to see if you can immediately identify the issue in the line of code
  2. Make sure to use Log.e(“tag”,”specific error note”) rather than in app toasts/popups. The UI execution thread can be blocked by other operations, but the log is written independent of execution.
  3. Always include e.printStackTrace(); in your try-catch blocks. Otherwise runtime exceptions fail silently.
  4. Isolate the last change that led to the issue (with code X it works but X+ doesn’t)
  5. Run through the code in your head (what should be executing/running/open)

Identify WHAT the issue is (get to a Google query)

  1. Look at stack Logcat errors/traces.  Any errors?  Any outputs that are not expected?
  2. Work your way down the call stack.  Start with the first method (onCreate) and work your way to the last method viewing variables at runtime along the way to make sure they are what you'd expect.
  3. Watch inheritance
    • A lot of pain has come from issues with overrides.  For example I assume my code is using java.library.newclass when instead it’s using mycode.newclass or android.newclass.

Finding a solution

  1. Google it to see if is a common issue
  2. Answers usually come from stack overflow/api documentation. 
    • Beware so sub-optimal implementations. There is a strong temptation using stack overflow just to paste in a solution to see if it works, but if you don’t understand what is going on it will introduce issues for you in the future
    • For example I added an animation sequence in android that overrode the onpause method. This caused an unhandled exception to fire every time I tried to call finish() or pause() or a user hit the home/back button. Huge pain to find and its not an issue that is immediately apparent (ie you’ll go 5-10 versions forward before discovering it. Then you need to backtrack).
  3. If you can’t find it you probably have another error in your code causing it
  4. This is a good time to roll back your code to the last time it was working and clean it all up/comment. 
  • This is good practice.
  • It is an opportunity to examine every line of code again to see if anything triggers an association with the trouble spot

Last Word: Version Control

Most of your errors will be caused by the last piece of code added. However, the tougher ones were introduced a long time ago, and you only found it now. Good version control lets you quickly step back in your version history to identify where the bug was introduced. Even if you are a lone wolf developer get your GitHub/SVN/CVS on.

Saturday, July 7, 2012

Since developing my first Android application I realized so much of the platform is undocumented.  I'm starting this blog to publish the various fixes/hacks/tools I'm using to get on my feet.  My pain is your gain.