Monday, September 30, 2013

Positive team culture

A positive and healthy team can have fun together. A healthy team is mature. Mature doesn't mean super serious - if you can't have fun, I can't see how you can enjoy your job.

Mature team members:
  • Don't complain about "too many" meetings but help improve efficiency & communication to reduce the number of meetings.
  • Don't play with their phones in meetings, but interact.
  • Don't feel embarrassed or under-qualified to question and correct other team members, even more senior team members.
  • Don't get offended or hurt when corrected by another member.
  • Don't get hung up on team hierarchy. We're all just developers.
  • Help and support each other. There is no point in individual success. There's no place for selfish behavior in a team. The product/company doesn't benefit if the team isn't working together.
  • Don't complain when asked for help. If you're the guy who always says "I've got my own work to do" then don't expect others to help you next time. I always remember this Ace of Base line from my school days: "To help another person will make you feel important". It's satisfying to help someone and a good learning experience on top of that. There is no better way to learn than to teach.
  • Have a sense of humor! Don't take things too seriously. We might as well try to have fun while we're doing this.
I admit this is much easier said than done. You need the right (i.e. compatible) people in the team and you need the right manager to motivate the team. There will definitely be some exceptions to the above, for example I'm sure there are some highly successful teams who don't see how I could even mention that I value a sense of humor, similarly I'm sure there are lots of funny but incompetent teams out there. However, I think these points above go a long way towards accommodating the widest range of personalities.

At a previous company, all teams had names. X-Men character names like Cyclops, Havok, Wolverine, etc. So when I started at my present company, I suggested giving the teams names. It wasn't a popular suggestion :-) Apparently I was the only one who thought that giving teams names like that was a 'fun' idea. Of course, that's perfectly fine, I just had to realize that this team has a different idea of what's fun than I did.

Sunday, September 29, 2013

How to fix "Install Parse Failed - Inconsistent Certificates" when installing .APK file

If you install an Android application (.apk file) to your phone from one machine, and then try to install it again later when it's built on another machine with a different apk signature (e.g. from a CI build) then you will get the following message on the phone:  (In this example I've tried to install the app from an email attachment directly on the phone.)

"Application not installed. An existing package by the same name with a conflicting signature is already installed."

Similarly if you try to install the app on another development machine using ADB (or from the IDE) you get the following "install parse failed inconsistent certificates" error message:

$ adb install TestProj-debug-unaligned.apk 
1539 KB/s (45347 bytes in 0.028s)
 pkg: /data/local/tmp/TestProj-debug-unaligned.apk
$ adb install -r TestProj-debug-unaligned.apk 
2659 KB/s (45347 bytes in 0.016s)
 pkg: /data/local/tmp/TestProj-debug-unaligned.apk

You also get the exact same message as above if you try to run the application from within Android Studio of course:

Waiting for device.
Target device: CB5A1QHGNF
Uploading file
  local path: /Users/lombard/src/TestProjProject/TestProj/build/apk/TestProj-debug-unaligned.apk
  remote path: /data/local/tmp/com.example.testproj
Installing com.example.testproj
DEVICE SHELL COMMAND: pm install -r "/data/local/tmp/com.example.testproj"
pkg: /data/local/tmp/com.example.testproj

You've got two options:
  1. Copy the first machine's debug.keystore file to the second machine. See: How to deal with INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES without uninstallation on StackOverflow.
  2. Completely uninstall the application first and then install again. You may have to do this if you don't have the debug.keystore file for some reason. Perhaps your Jenkins CI build has a different release keystore.
I've had to go for the second option.

I was hoping I'd be able to keep the application's data, so I first tried uninstall with the -k option to keep the data files, however that results in an "update incompatible" error:

$ adb shell pm uninstall -k com.example.testproj
$ adb install -r TestProj-debug-unaligned.apk
1532 KB/s (45347 bytes in 0.028s)
 pkg: /data/local/tmp/TestProj-debug-unaligned.apk

The only solution seems to be to uninstall the application completely:

$ adb uninstall com.example.testproj

Now the app will install from Android Studio.

Ideally I want to find a way to force an app to reinstall without needing to completely uninstall it first.

Wednesday, September 18, 2013

Nexus 7 with wireless keyboard and mouse

A few months ago I cracked my Google/Asus Nexus 7 screen/digitizer and the touch is no longer working on 90% of the screen. Only a small part in one corner still detects touch. The display still works fine otherwise, but it was essentially useless.

I looked into several ways to try and make the Nexus 7 usable again, including:
1. Tried to find an app that might all me to use the small working touch area to control apps (e.g. keyboard apps that can be controlled without needing the entire screen);
2. Tried to use MonkeyRunner to script apps to control them. However, this required me to accept the PC in USB debugging mode, which I couldn't do without being able to tap on the "OK" button...
3. Tried to find a cheap replacement screen/digitizer on eBay but I wasn't willing to spend more than EUR60.
4. Seriously considered getting a new Nexus 7 2013 model.

Eventually I've found an amazingly simple solution to make it fully usable again: A cheap OTG cable (Micro USB male to USB female), which allows me to plug my Logitech K260 wireless keyboard & mouse into the Nexus 7.

It's not exactly a tablet anymore, but compared to a broken piece of unused electronics lying in my drawer, this is great! The Nexus 7 with keyboard and mouse is now basically like a small Android laptop. Still perfect for surfing the web etc. I'm extremely happy that for only 3 GBP I've now got a working device again.

Tuesday, September 17, 2013

How to configure the Samsung Galaxy 5 / Europa to work with ADB / Android Studio

I want to deploy an Android application from Android Studio to an old Samsung GT-I5500 (known as Galaxy 5 or Galaxy Europa) running Android 2.2 Froyo (API level 8). (Yes, it's probably worth testing on old phones too, although I admit Froyo is at the very bottom 2.4% of distributions!)

Summary of steps:
  1. Enable USB debugging
  2. Select USB connection mode to "UMS mode only"
First enable USB debugging by going to Settings -> Applications -> Development -> enable "USB debugging".

Plug in the USB cable from the computer to the phone. The phone will pop up the "Setting USB" dialog and ask you to select "KIES" or "UMS mode only". You want to select the first option: UMS mode only. (Kies is Samsung's software for updating the phone's software etc).

Now the I5500 shows up on my devices list in Android Studio. My Android application was configured for minSdkVersion 10 so notice the "no" in the Compatible column when I tried to run the application:

I modified the build.gradle file to minSdkVersion 8 and also set android:minSdkVersion="8" in the AndroidManifest.xml file. Now the app deploys OK.

Of course ADB.exe also lists the I5500 correctly now:

D:\Android\android-studio\sdk\platform-tools> adb devices
List of devices attached
I550030d7c481   device

Thursday, September 12, 2013

OK, I admit it! I was wrong!

This morning I saw this tweet:
I had a similar thought earlier this week at work. As many others, I've always got a long To Do list and it never seems to get any shorter. As result, I try to prioritize as I go and sometimes I don't make the wisest choices and some very important tasks fall way behind schedule (even though they remain at the top of my To Do list for weeks!)  This week one such task culminated in my manager coming over looking for the reasons why I hadn't completed the work yet, as the issue is now highly visible. I went into a half hour rant explaining the various reasons and excuses why I couldn't finish the task. That night, in bed (probably around 3am, the time when I usually reflect on this type of thing), it occurred to me that I was being completely dishonest to myself and my manager. The simple reason I have not yet finished that task, is because I find it boring and I will always pick a more interesting task that I can justify to myself as being more "urgent" at the time. The next morning I talked to my manager and admitted: "The simple answer is: I found it boring and I made some judgement errors in my prioritization and procrastinated too long." It feels good to take responsibility for your mistakes.

This ability we have to find excuses to justify our decisions even when we're wrong, is called Cognitive Dissonance. Check out the book called "Mistakes were made (But not by me)". It covers this topic quite well, I recommend it.

As developers, we want to prove ourselves. We want to be right about our opinions and we want others to see our point of view. It's difficult to be completely unbiased when there is any room for ambiguity in a debate.

I'm sometimes lucky to catch and recognize the feeling of the cognitive dissonance as it sets in, and that makes it easier to control it. It helps a little bit just be aware that we're all susceptible to biases and cognitive dissonance, but I doubt anyone can completely eliminate it.

For many years I've been keen to try doing regular Code Reviews at work, but I'm "worried" that my team members may feel insulted when I "criticize" their code. At the same time, I feel like I can handle the criticism myself. Does that mean I'm mature enough not to experience cognitive dissonance when faced with disagreement, or is that a type of bias in itself to think that I'm somehow less susceptible to the emotional effects of criticism and conflict? (By the way, no one should feel offended when their code is criticized - you are not your code).

As software developers, I think we are often too scared of making any mistakes. Especially "debilitatingly-perfectionist" and High C developers like myself. We want certainty and facts. We want to stick with the tools we know. We get religious about our tools (languages, text editors, brands of keyboards, etc) and we can't understand when others can't see that they're wrong and we're right.

We have to learn to embrace risk, taking chances, making mistakes, and admitting our mistakes. The Agile mindset is to embrace failure (fail early). Learn to make better mistakes in the future. Making mistakes is the key to making progress, as Daniel C. Dennett says in his book "Intuition Pumps and Other Tools for Thinking".


Sunday, September 08, 2013

Remote Desktop Connection for Mac OSX - cannot verify the identity of the computer

Short version: If you have issues with the Microsoft RDC for Mac client connecting to Windows Server 2012 R2, then give CoRD a try.

I'm having a lot fun playing with Azure lately. It's so quick and easy to create new Ubuntu- or Windows-based VM servers for trying something, and then deleting the virtual machine again when I'm done. For the Ubuntu servers I just use ssh of course, but for Windows Servers you need to use a Remote Desktop Connection client.

At home I connect to the Azure cloud services on OS X using the "Microsoft Remote Desktop Connection for Mac" RDC client. It's just cool seeing the remote Windows server on the Mac. I don't even need to use VMWare or Parallels to run a local Windows installation.

However, I've come across this error on the Mac when trying to connect to a remote Windows Server 2012 R2 on Azure:
"Remote Desktop Connection cannot verify the identity of the computer that you want to connect to. Try reconnecting to the Windows-based computer, or contact our administrator."

When this happens, the only solution currently seems to be to use CoRD instead of the Microsoft RDC client.

First ensure you've disabled the "Allow connections only from computers running Remote Desktop with Network Level Authentication (recommended)" setting. To do that, first connect to the remote Windows Server 2012 R2 using RDC on a Windows client, then go to Server Manager:

Go to Local Server -> Remote Desktop. Make sure the NLA setting is unchecked:

Now get CoRD from

Add the server, making sure you've got the correct domain name for the Windows login:

Now you should be able to connect successfully to the remote Windows 2012 R2 server in the cloud.

On other versions of remote Windows servers you may also have success trying the following with the Microsoft RDC client for Mac:
  1. Close Remote Desktop Connection for Mac
  2. Go to: Finder -> Documents -> RDC Connections
  3. Move the Default.rdp file to Trash
  4. Open RDC again and connect to the server.
  5. When the Enter your credentials window pops up, the Domain field is populated with the DNS name of the host, which isn't necessarily the correct domain name. Try the correct domain name or try clearing this field.
  6. Just supply the correct username and password. Click OK.