My HTC One Review

I've been an iPhone user for the past five years, except for a few weeks in 2011 when I used an Android phone to see how good it was. At that time, my evaluation was that Android was a second-rate knock-off of iOS.

But, with the releases of Android 4.0 "Ice Cream Sandwich" and 4.1 "Jelly Bean", Android got a lot less ugly, and hardware is finally fast enough that it doesn't feel so slow. Because I make about half my income from Android app development, I decided it was time to give Android another try as my personal phone. I vowed to put the iPhone away, buy a top-of-the-line Android phone, and use it for at least 12 months. My goal was to immerse myself in the Android ecosystem and learn how "regular people" use their Android phones.

When I made this purchase in July, the two top-tier Android phones were the Samsung Galaxy S4 and the HTC One. I've hated the two Samsung devices I've owned (Samsung Galaxy S and a Samsung Galaxy Tab 2 7.0), so it was an easy choice.

I won't re-hash the things that all the other HTC One reviews say. These are my personal impressions, and what I do and don't like about the HTC One may not match your preferences.

Trying Out CyanogenMod on a Samsung Galaxy Tab 2 7.0

Last year, I bought a Samsung Galaxy Tab 2 7.0 for use as an Android development/testing device. I didn't expect it to be good, and it wasn't. It was slow, clunky, and ugly in comparison to the iPad, just like every other Android tablet. But it was cheap, and I only used it to test apps I was developing, so it didn't bother me much.

Earlier this year, it finally got an upgrade to Jelly Bean, which improved the slow/clunky aspects, but it still wasn't good. I bought a new Nexus 7 in July (which is an awesome Android tablet), so I went to to see what they would give me for a used Galaxy Tab 2 7.0. Their offer: $16.

So, it went into the old-devices drawer. I kept it only because I might need it in an emergency if my Nexus 7 died at the worst possible time.

When all the news and drama about CyanogenMod (CM) broke last week, I decided I would give CyanogenMod a try. I was curious, and I had a device available to "sacrifice".

And you know what? That crummy old Galaxy Tab 2 7.0 is actually a pretty nice tablet with CM installed. I now have an Android 4.2.2 Jelly Bean tablet without all the Samsung TouchWiz crapware. It's not as good as the Nexus 7, but it no longer feels like junk, and it might stay out of that drawer for a while.

If you have an Android device in your junk drawer (or a Kindle Fire, or a NOOK), you might want to give CM a try. Read on if you're interested.

Setting Up a New Mac, My Way

Over the past couple of weeks, I've set up a few Mac OS X machines to do development of iOS and Android apps. Doing this used to be an all-day chore, but things like app stores, iCloud, and Dropbox have streamlined the process a lot.

(I could streamline the process even more by cloning an existing drive or virtual machine, but I'd rather install everything from scratch to avoid the presence of old cruft.)

As a reminder to myself, and to help out anyone else who needs to do this, here is my procedure for setting up an OS X machine the way I like it:

  1. Install/re-install OS X.
  2. During the OS X setup process, use the same login account name and password that I use on other computers, and provide the Apple IDs for iCloud and iTunes (which are different, in my case).
  3. Open System Preferences and do the following:
    • In the General panel, set Sidebar icon size to Small and Show scroll bars to Always.
    • In the Mission Control panel, uncheck the Automatically rearrange Spaces based on most recent use box.
    • In the Mouse and Trackpad panels, set all speeds to two ticks less than the maximums, and enable all the gestures.
    • In the Keyboard panel, set Key Repeat and Delay Until Repeat all the way to the right, and check the Use F1, F2, etc. keys as standard function keys box
    • In the Keyboard panel, go to the Shortcuts tab, select Services, and then enable the New Terminal at Folder service.
    • In the iCloud panel, enable everything.
    • In the Sharing panel, set the Computer Name to something unique (not "Kristopher's computer") and enable Remote Management, Remote Login, and File Sharing.
    • Set up Time Machine
    • If this is a virtual machine, go to the Desktop & Screen Saver panel and turn off the screen saver, and go to the Energy Saver panel and set the sleep sliders to Never.
  4. Use the Software Update... menu item to install any system updates that are available, and reboot if necessary.
  5. If this is a virtual machine, install VMWare Tools or Parallels Tools.
  6. Download and install these packages (using serial numbers and licenses stored in 1Password):
  7. Open the App Store app and install these applications (skipping any that are not needed):
    • Xcode
    • CodeRunner
    • OS X Server
    • Moom
    • PopClip
    • Alfred
    • Pages
    • Soulver
    • Evernote
    • Sketch
    • Skitch
    • Pixelmator
    • MultiMarkdown Composer
  8. Open Xcode, accept the license agreement and download simulators and documentation. On a Terminal command line, execute xcode-select --install to install the command-line tools.
  9. Install Homebrew
  10. Open the Terminal application and run java. Download and install the JDK when prompted.
  11. Download and install the ADT Bundle. (Note: This is old; now Android Studio is the thing to download and install.)
    • After installation, launch the Eclipse application. Choose the Android SDK Manager menu item, and install/update everything in these subtrees:
      • Tools
      • Android 4.3 (or whatever the newest API level is)
      • Extras
    • Choose Help > Install New Software.... Click the Add... button. Add this repository and install the Eclipse Color Theme plugin:
      • Name: Eclipse Color Theme Update Site
      • Location:
    • Download and install latest the HAXM driver from (If that link is broken, go to and look for a HAXM download link.)
  12. Set up ~/.bashrc to run my shared scripts that are in ~/Dropbox/bin.
  13. Execute this in Terminal: chflags nohidden ~/Library
  14. Set up ssh keys for Bitbucket and GitHub.

Then to verify everything is ready to go, I use Git to grab the source code for an iOS app, and build it and run it, and then do the same for an Android app.

(For my Windows setup, see Setting Up Windows, My Way.)

Transferring Ringtones from iTunes to an HTC One

I had some ringtones purchased from iTunes that I wanted to put onto my new HTC One. Googling for instructions found many hits, but many of those pages were a few years old, so the instructions didn't work anymore, or they didn't work with the HTC One, or were six-minute-long YouTube videos. So, I'm writing up some simple instructions that worked on my HTC One. (They will probably work with other Android phones, but I'm not promising anything.)

First, on your computer with iTunes, find the ringtones you want to transfer. These will be files with a .m4r extension. On my Mac, they were in the directory /Users/kdj/Music/iTunes/iTunes Music/Tones.

Next, you need some way to get the files onto your device's /sdcard/Ringtones directory. If you have a Windows computer, I think you can just plug the phone into the computer and it will be mounted as a USB drive, so you can just drag and drop the files. If you have a Mac, you can either use the Android File Transfer application, or use something like Dropbox.

Finally, you need to change the filename extensions of the files in /sdcard/Ringtones from .m4r to .m4a.

Then, on the device you can go to Settings > Sound > Ringtone, and you should see your ringtones in the list.

Solving "Symbol not found: _Perl_Gthr_key_ptr" When Running git-svn on Certain Unnamed Operating System Beta Versions

Let's say that you are using a beta version of a new operating system that you can't name because it is covered by a non-disclosure agreement, and you have also installed the newest version of its development tools, which are also covered by NDA, and when you try to run the git svn command, you get this output:

dyld: lazy symbol binding failed: Symbol not found: _Perl_Gthr_key_ptr
  Referenced from: /usr/../Library/Perl/5.12/darwin-thread-multi-2level/auto/SVN/_Core/_Core.bundle
  Expected in: flat namespace

dyld: Symbol not found: _Perl_Gthr_key_ptr
  Referenced from: /usr/../Library/Perl/5.12/darwin-thread-multi-2level/auto/SVN/_Core/_Core.bundle
  Expected in: flat namespace

error: git-svn died of signal 5

Apparently, the problem is that git-svn is implemented in Perl, and there is something wrong with the Perl configuration used when you run /usr/bin/git.

What do you do?

It turns out you can fix this by putting the Git executables provided by the new development tools at the head of your PATH, by executing this command (or adding it to .bashrc):

export PATH="/Applications/":$PATH

where is the unnamed development tool.

Alternatively, you can add all the command-line tools to your PATH like this:

export PATH=”/Applications/”:$PATH

Credit to Vandad Nahavandipoor for the hint.

Another option would be to use the xcrun utility to run git. You can do this:

xcrun git svn blah-blah-blah

or put this into your .bashrc so that you don't have to remember to type xcrun:

alias git='xcrun git'

If you are the kind of person who thinks its a good idea to replace system files with symlinks, you might try symlinking /usr/bin/git to /Applications/ However, that alone doesn't work, because Git will still run the git-svn executable from its default location, /Library/Developer/CommandLineTools/usr/libexec/git-core, and you will still have the _Perl_Gthr_key_ptr problem. So you also need to symlink the default location to /Applications/, or set the GIT_EXEC_PATH environment variable.

Customizing Android Action Bar for Edit Mode

I spent a long time trying to get a contextual action bar (CAB) working for an editing mode in an Android app I'm developing. My goal was to have a CAB appear whenever the user started changing field values on a screen, and the user would tap the Done button when complete. The CAB would also show a "Revert Changes" button allowing the user to undo whatever they did.

This initially seemed like the easiest way to indicate to the user that they had made changes and needed to explicitly save them, but Android's default implementation of CAB has some drawbacks:

  • The standard button is titled "Done". I would prefer it to be "Save", but there is no easy-to-use setTitle() method available.
  • If user hits the BACK button, the CAB disappears, and there is no straightforward way for the app to determine whether the CAB disappeared because the user hit Done or because they hit BACK, or any way to intercept the processing of the BACK button while a CAB is displayed.
  • I have to write code to restore the CAB state on a configuration change

While browsing around the web trying to find examples of workarounds for these issues, I ran across a blog post explaining why using a CAB for this scenario won't work, even if I did fix the aforementioned problems:

Edit Mode and why using a Contextual ActionBar is a bad idea

(Short version: If user double-taps or long-presses an edit field, it will pop up its own text-selection CAB which would blow away my CAB and eventually lead to a NullPointerException.)

So, I'm not using a CAB, but will instead customize the look of the non-contextual action bar as suggested in that blog post.

Removing a Broken Lightning Connector Plug from an iPad or iPhone

Newer models of the iPad, iPhone, and iPod touch use the Lightning connector instead of the old 30-pin dock connectors. The Lightning connector is smaller and you don't have to worry about inserting it upside-down, so on the whole this is a good change. However, the connector plug is not as sturdy as the old plug, and my wife somehow broke the plug off inside her iPad.

It is pretty easy to pull a broken plug out:

  1. Get a small screwdriver (small enough that the head will fit in the Lightning port)
  2. Put a small drop of super glue on the tip of the screwdriver
  3. Insert the screwdriver into the socket and hold it against the broken plug. Be careful not to touch the sides of the socket with the super glue.
  4. Wait about 30 seconds for the glue to set.
  5. Pull it out smoothly. The Lightning plug isn't held with much force, so this should be easy.

Unfortunately, there is no way to repair the cable, so you'll have to go to your friendly neighborhood Apple Store and give them twenty bucks for a new one.

Android SDK Tools 22.0.1 Considered Harmful

After finishing up some work on an iOS app today, it was time to go make equivalent changes to the Android port of that app. "I'll just update my Android SDK before I get to work," I said (to myself). I opened the Android SDK Manager and let it update these SDK packages to these versions:

  • Android SDK Tools: 22.0.1
  • Android SDK Platform-tools: 17
  • Android SDK Build-tools: 17

Then I let Eclipse update the ADT. Then I got to work. I opened my Android app project and tried to run it. I found I couldn't make a working debug build or a release build, nor could I create a signed APK to install on a device.

After a few hours of hair pulling, I got everything working. Here is what I learned. I hope it helps someone.

UIColor Category for Specifying Packed RGB Values

iOS's UIColor class makes it pretty easy to specify a color using red, green, blue (RGB) and alpha components:

 // set pale yellow color
 label.textColor = [UIColor colorWithRed:1.0

However, as with many Cocoa API's, it's pretty verbose. Web developers would specify that color using the hexcode shorthand #ffff80, and many graphics editing tools would generate a hexcode value like that rather than values in the range 0.0–1.0.

So I made a simple category on UIColor that lets one write stuff like this:

#include "UIColor+KDJPackedRGB.h"

// ...

// set pale yellow color
label.textColor = [UIColor colorWithRGB24:0xffff80];


Death, Numbers, and Risk

Here are some numbers that many people don't know, or don't want to think about:

There are approximately 6.9 billion people in the world. On average,

  • about 55 million people die each year,
  • about 1.05 million people die each week,
  • about 151,000 people die each day,
  • about 6280 people die each hour, and
  • about 105 people die each minute.

Source: Wolfram Alpha

There are approximately 309 million people in the US. On average,

  • about 2.5 million people die in the US each year,
  • about 48,000 people die in the US die each week,
  • about 6860 people die in the US each day,
  • about 286 people die in the US each hour, and
  • more than 4 people die in the US each minute

Source: Wolfram Alpha

In round numbers, that's over 150,000 people dying every day, and almost 7,000 people dying in the US every day.

Many of these deaths are those of elderly people passing away in their sleep. Many are unmourned. But many are tragedies in the sense that a person has died too young, and grieving people are left behind.

So, when the news presents reports of people dying, ask yourself: Why is the news reporting these deaths, and not the 150,000 other deaths that happened today around the world, or the 7,000 other deaths that happened today in the US?

Is it because the reported deaths are more important than all the others, or is it because somebody found a way to make dramatic stories out of these particular deaths? Are the reported deaths indicative of larger patterns or important trends, or are they interesting because they happened in a public place and there is video available from several angles?

In fact, your chance of being killed by a terrorist or a mass shooter or an airplane crash or flesh-eating bacteria or a meteor or anything else reported by the media is almost equal to zero. These events are reported on the evening news because they are so rare.

So be careful about letting what you see on the news control your fears.

It is silly to worry about terrorists and mass shooters if you smoke cigarettes, eat a lot of fast food, or use your mobile phone while driving. The latter activities could kill you; the former just don't happen often enough for any reasonable person to worry about them.

You might want to turn your home into an armed fortress to protect your family from dangerous people. Before you do that, you should ensure that your family is eating healthy meals, getting lots of exercise, and getting regular medical checkups. You are more likely to save somebody's life by learning CPR and First Aid techniques than by learning martial arts or small-arms tactics. Make sure all the smoke detectors have fresh batteries before you worry about installing a high-tech security system.

When someone asks you to pray for the victims of some tragic event, ask why you should pray just for them, and not for the one million people who died in other ways that week, or for the million that died the previous week, or for the million who will die the following week.

When somebody tells you that thousands of people are killed every year by some disease or government policy or widespread moral failing, and insists that drastic measures are justified to prevent those deaths, think about the 2.5 million Americans who die of other causes every year. If someone claims that a new law or policy is worthwhile "even if it saves only one child", consider whether resources might be better devoted to policies that save hundreds, thousands, or millions of children instead of just one.

I'm not suggesting that we do nothing to try to prevent deaths, or that we should not care when strangers die. If you can save one person's life, you have done more good than most people will ever do. I'm just suggesting that you remember the bigger picture.

With billions of people in the world, it will always be easy to find instances of evil people doing horrible things, and of innocent people dying in tragic circumstances. But remember, while around 150,000 people die every day, a larger number are born, and billions of people just go on living.

Your chances of making it through the day are pretty good.

Syndicate content