Wednesday, December 26, 2012

Useful tool for getting Android crash logs - free

One of our QA staff had loaded our Android APK that is still in the testing phase and was getting a crash. This means nothing is being sent to the Google Play Store. Previously I would have them set up the Android SDK on their box and grab the crash or just drop by my office. This person works remotely. I needed a new solution. I found the following app on the Play store:

It is called Log Viewer and will let you view the log on the device or email it to someone. Turns out she had an out of date APK and the issue had already been fixed. Easy this time but next time...

We do have another remote device that is crashing much later during the app run. I am going to have them install this and get me the report so I can track that down. Very handy tool. I installed it on my phone too as there are times I am demoing something I am working on and it never fails I will crash it in some very odd manner. Now I can just email myself the crash and deal with it later.

Wednesday, November 28, 2012

I hate McAfee

I absolutely hate McAfee antivirus. It sucks your CPU dry. This is the second company that I have worked at that uses this pile of crap. It makes my machine nearly unusable. I have used other anti-virus software that does not cause this issue.

McAfee insists on looking at every JAR file. Since they really are ZIP files it wants to open and unzip and look all the damn time. It is killing me. We had the tech team set up some exemptions and that worked for a bit but I have a feeling they got wiped out and I am back to not being able to write code. Anything using JAR files is super slow. I can't get any work done this morning so I decided to bitch on my blog instead.

I don't get viruses. I don't download stupid crap. I don't fall for scams on the internet. I just want to code but today I can't do that due to a piece of crap software that as NEVER during my time using it ever caught anything on any computer that I use EVER. I have put up with this crap for year and I hate it, hate it, hate it.

There has to be a better way for it to ignore stuff it has looked at 50 times already in a single day. Come on people, your software sucks and it is ruining my productivity. It has never helped me in the 6+ years I have been tortured by your crap.

Saturday, November 24, 2012

Only doing Android work - what a change of pace

At my new position I am only doing Android development where before I was doing Android / iPhone and desktop Java. First off it is a bit weird only having one computer, one IDE, one mouse and one keyboard to deal with. Everything is the same each day. You don't have to mentally switch gears multiple times a week.

What it does make you think about is pushing the one platform you are on even farther than before. I was always in a bit of a rush. I needed this working on both iOS and Android so I got it working on each but maybe not the best on each. Now I can say "I need this working on the Android and I need to to work and look the best possible." I don't care if what I am doing it pain in the behind on iOS, there is another team to worry about that. I don't have to think about desktop Java at all.

I am finding this new mentality is really helping me discover areas of the Android platform I had not had the time or energy to investigate in the past. I have been playing around with animations. We need to swap an image view between the front and back of a check. I started with a simple one, changed it to a fade in / fade out as suggested by another developer then I switched it again on Friday to a simple animation that makes it look the check is flipping. I am pretty happy with the current iteration.

The other bonus is I have the ear of a second Android developer. Being the solo mobile guy at the last place had a number of disadvantages. No one to bounce ideas off of, do code reviews, suggest a better way, a new animation, better color schemes, different layout ideas etc. The other guy has a lot of different Android experience than I do. He had worked with JSON before so got that part running quickly. I had done custom controls and a lot of layouts so I had that handled. We both know to use styles, the string table and other XML files to keep things clean.

The code we inherited looked like it was the first Android project written by this off shore team. We had a lot of general clean up to do before we even wanted to touch the guts as they did not follow any of the general Android guidelines.

We are finishing up the process of making this a real Android app. They locked all the screens into portrait. That may be acceptable for a game but not for a main text based application. The iPhone team locked it all into portrait too because doing both portrait and landscape under iOS can be a pain. Sure, there are some gotchas in Android but it is pretty darn flexible on the layout side of things and it is easy to create the directories you need. Plus we are working on having it look nice on phones and tablets. The iOS team is not doing a universal app so iPad owners will get the less the satisfactory 2x experience.

They are not too worried about Android tablets telling us there is little demand there. Not sure they are looking forward enough. There are going to be a lot of 7" tablets from Google and Amazon under the tree this year along with iPads and iPad minis. I know I use my tablet a lot around the house and I figure more and more people will be using them too. For this battle I am making sure it looks nice and is operational on a tablet. It is not tablet optimized but if you use a tablet I don't want you to scream and run away when you fire up this application.

I would suggest they do a universal app for iOS too but I think that will fall on deaf ears. The current team is very new to iOS, learning it on the fly in fact. Since I sit a converted break room with the other Android developer and two of the iOS team I get to hear their issues. Most of them I know about having done iOS development for a year. At least they are going after iOS 5.x and above and can use the new memory management aspect. The current code does not but all new code can. That will be a huge help. I was using that on the final iPad project I worked on at the old job and I know I could get used to doing it.

The one thing I really miss from the old job is dual 24" monitors. I have a dual screen set up now, the laptop screen and a 21" screen with a less than stellar resolution. The Android emulator barely fits on a screen height wise. Developing means you have a ton of windows open: Outlook, instant messenger, browser, text editor for notes, Eclipse, emulator, music player, command prompt, paint program, etc. These little 1400x900 screens just don't cut it. A a contractor I am considering picking up a bigger screen and hauling it in just to keep my self slightly sane. Companies need to realize how important screen space is to a developer. My dual screen set up at home is a better configuration than I have at work and that is kind of sad.

All in all it has been a good experience so far. They have work lined up so I know there is plenty to do. I am becoming a better Android programmer every day and using more of what the SDK has to offer. As long as I am growing at a job I am happy. The people are friendly and having another Android coder next to me has be a huge help.

Saturday, November 10, 2012

Life at the new job and a Galaxy Note as my testing device

Life at the new job has been interesting. They did not have an official place for me to sit on the first day so I took over the office of a guy who is on vacation. They found a place over in customer support so I moved there for a bit and now will move to a more permanent home in what use to be a small conference room that is being divided into 4 cubes. I will be in there with another Android developer and two iPhone developers. Will help us share a lot of ideas.

For my main testing device they gave me a Galaxy Note - original version not the new II. For some reason I thought it was going to be much larger as all the reviews jump all over that. It is larger than my main phone, a Galaxy S Vibrant. I actually like the size. Larger than my phone but not a tablet. I have been using it a lot a night to see what I think of it as I have considered getting a Note II when it goes on Black Friday sale, or at least I hope it goes on sale.

I wish the S-Pen worked a bit faster. I am hoping it does a better job keeping up on the Note II. On the model I have I must slow down my standard writing speed to have it draw what I think it is going to draw. I should not have to adjust to what the device can do, it should keep up with me. I have used the phone as a mini whiteboard. Again, drawing speed is a little slow but if I match the pace it works well. Using it to jot down notes at home is also handy, it sits right next to me and saves me from hunting down paper to remember something like "out of cat food". You can easily erase mistakes in your drawings too. I think this could be a great feature.

As far as a testing device it is really nice. Samsung seems to be very quick to grab back memory you once used and to kill activities as you move between them. It allows me to simulate low memory usage that would occur on a phone. This really comes into play as I am doing a lot of importing of images from the camera activity which is one area you can quickly run into memory limitations. I have been able to fix all the issues I have run into and make my code much more low memory proof than previous code I have written. Allowed me to learn all sorts of interesting things about Android programming.

After using the phone for about a week I would say it is a winner. I have been using it at night instead of my Xoom when I put my son to bed. At that time I am generally reading web pages, using Pulse or maybe playing a game. Being able to do that with one hand is really nice. I don't know if a 7" tablet would allow me to do the same thing or not as I don't have access to one. The Note fits in the hand without cramping. The screen is very bright and readable. I only charge is once a day. Web pages tend to be read in landscape mode but that works just fine. You get the side to side space you need for most websites but you do have to to a bit more scrolling vertically as you read pages. Nothing that is annoying, just something to keep in mind.

After I have time to test the S-Pen drawing speed on a Note II and it goes on sale I will probably buy one as my next personal device. I love the Xoom tablet and use it a lot. My phone is getting older and it only runs 2.2 which is pretty crappy. I need to use some of the new Android OS features to keep up with the programming world.

Working strictly on mobile development at my job has been nice. No shifting gears between iOS, Android and desktop Java during the day. One keyboard, mouse, language and IDE to keep straight.  I am happy I know Objective C so I can look at the code and see what they did as my first project is a conversion of the automatic check deposit functionality, thus me taking a lot of pictures. I am sure my cube mates are sick of hearing the sound of a camera shutter as am I. Friday morning I fixed my threading issue so I stopped taking pictures and started looking into the server API for send the deposits.

Being as I am a contractor I get to work Monday which the perms have the day off for Veteran's Day. I will be happy when I convert to a full time person allowing me to have all the bank holidays off like I did when I worked in the stock market industry.

Thursday, October 25, 2012

Changing jobs

Today is my last day at my current position. I learned a lot about mobile development being the sole developer for both the iOS and Android product. I have also written a game that is free out on the Android market called Grid Hunt and am working on another Android side project.

For my current position I do WebStart Java Application work too along with project management and graphics artist work. For the new position I will be start with Android specific programming. They already have the iOS side up and running. I will work on converting that to Android. They plan on having the mobile team being able to work both sides of the mobile OS platforms. I already have a nice head start here.

I am excited and nervous to change jobs. Excited as I will no longer have to do all the project management and graphics artist work. I will start with a specification and get to code away. I also will not be switching IDE, keyboard, mouse, monitor and programming language multiple times a week. This allows me to really hammer down on Java / Android under Eclipse. I really like Eclipse and find it to be super fast for my programming style. IntelliJ IDEA is fine too, which is where I did my desktop Java work, Xcode stinks but AppCode was pretty good for iOS development. I will not miss Xcode and its various limitations nor will I miss Objective C as a primary programming language. I will of course still see it as I can pull that code and look things over during the Android conversion.

Nervous because you have to learn the ins and outs of a new environment. What version of Agile are they using? Bug tracking? Version Control? Who is who when it comes time to ask questions? How locked down is your development machine? When do people eat lunch and where do they go? What are core business hours? Can I work from home? Do others comment the code and use comments when checking in code? Braces on separate lines? TAB or SPACE? Is the current code base solid or kind of spotty? Is there a solid understanding of OOP? What format does the data come from the server? Does each developer have a piece of test hardware or is it shared? Do they allow wearing of headphones or music at all? Where is the bathroom, break room, copy room, etc? Weird office politics? General sense of humor? Dress code specifics? Flexibility of work hours? Time reporting rules? Base hardware? Web surfing rules?

Yeah, it is going to be an interesting day on Monday as I begin to figure things out. I will get back into the flow of being a kick tail programmer pretty soon and then it being at work will become and easy habit and I will know a ton of new people. All of 20 blocks from where I currently work so I can visit the old staff over lunch easily enough. I am ready to be a full time Android developer. Always more to learn about that platform.

Tuesday, October 9, 2012

Dialogs - gather data or do everything?

Should a dialog box simply gather data or should it do the processing on the data too? I have seen it done both ways in code with things intermixed in the same project. It gets very confusing when the two styles are mixed.

What exactly do I mean? A dialog box has a number of controls such as text fields, check boxes, lists etc. They gather information from the user as to what to do next such as printing a document, searching on criteria or choosing data to add to a table.

In the actual dialog box code you can also have it act upon that data and do the print job, perform the search or write data to the table but should you? I think the dialog should not perform the operation, it should only collect and validate the data.

Why do it that way? This keeps the processing separate from the UI. It allows you to run the print, search or table add in a headless manner, you don't need the dialog to appear to perform the operation.

So why do people chuck it all in the dialog? Because you already have all the data. Why pass it back and forth between the dialog and the operation? Boy that is annoying! Yes, there is more code involved to pull the data gathered out of the dialog. You can use separate method calls for each data item, a map or other collection type to get it back to the calling program. It really is not that big of a deal and it will save you a lot of time later when you need the operation separated from the UI. Lazy programming will come in bite you in the behind every time.

Don't cheat and make methods on the dialog object static so you can call them without invoking the dialog. That is a misuse of objects.

A lot of times the operation can take a lot of time. You want to show a busy state in the application and possibly run it on a background thread. Maybe the processing - such as printing - can run while the user does something else. If you leave this all in the dialog code that crazy UI sits on top of your app until processing is over. That is not very friendly. The dialog does not need to know about how the processing should be done. Is it quick and easy, does it take a long time and must complete before they move on to the next step or can the whole operation run in the background while the user moves on to the next task? Different data set sizes may need different processing actions. Don't lock all of this down in the dialog.

Thursday, October 4, 2012

Which way to go for mobile permissions?

Which way do you like better for mobile permissions - Android or iOS? Android has you build the permissions into the program via the manifest file. iOS asks for permissions as the program runs. Both have pros and cons.

Developer decides on a list of required permissions, must adhere to them
Compiler enforces permissions
User gets to see all permissions at time of program install / upgrade
Permissions as static and included in app binary, don't have to be stored in associated data area of device

Permission list may change during OS updates
User forced to read list during install, most ignore and just install, later complain you did something crazy
Some permissions are not granular enough
Some permission you would like to have but are not required to run - how to handle that?

Developer codes away, does not really have to think about it
Old cheating programs are now caught when action is requested
New permissions can be prompted with OS upgrade

User is bothered during program run, might scare them
Developers were able to cheat before, can still cheat until OS upgrade catches them
OS trust instead of IDE support, your app could fail due to user saying NO, defensive programmer for run time issues
Need special storage to keep track of each permission granted per application
User has to go under settings, privacy to find what they have granted if they want to make changes

I am undecided on which way I like better. I am happy to see iOS is now addressing this issue. Previously it was the wild west in iOS land. I just saw a prompt while running my code as I allow you to choose images from the gallery to attach to medical cases. What I am doing is innocent but I can see where programs could easily abuse this privilege. I was pleased to see the prompt appear and to have it only prompt once.

Wednesday, October 3, 2012

What will the iPad mini bring to the table?

Have you already hammered out adjustments so your app will run on the iPhone 5? Has it been submitted to the App Store? Are you waiting on it to be accepted? I have updated our app to run on the iPhone 5 but have not tested on actual hardware yet so I want to wait for that to happen before I submit.

It did get me thinking about the iPad mini. First off if it actually exists what resolution will it be? Should it be double the size of the iPhone 5? That makes some sense to me as they are looking at videos and deeming the wide screen presentation is the way to go. Will it be same resolution as the iPad 3 in a smaller package? Makes it easier on tablet development and really that resolution is fine for a 7-8" screen. Heck there are much smaller Android phones running higher resolutions than the iPad.

Let's say they go with a new resolution. You get to update your app yet again. The main app I have is universal - same code runs on iPhone / iTouch and iPad. The update to iPhone 5 was pretty simple as I try to avoid hard coding. Since I also wrote the Android version I already need to think resolution agnostic. I tend to not think in absolutes coming from a PC background. Hopefully my code will port quickly.

I have special checks in the code now for the iPad as the status bar is the same height in portrait and landscape mode on the iPad where as it changes height on the iPhone based on orientation. I really wish you could query controls for their current / minimum / preferred dimensions. Maybe in a future release of iOS.

At this point I think I am better off waiting to submit anything to the Apple Store until the iPad Mini release is confirmed for October or nothing happens. I can submit one app and catch all the new resolutions. I will have to decide if just testing via the simulator is enough. Since I know my app runs fine, as far as speed is concerned, on actual devices how far can I trust the simulator? It gets tough for a small company to buy a lot of testing hardware. I know I have already put a lot of faith in the various Android emulators and so far have not run into issues and I can see from our Google Analytic data that our users have a wide range of Android devices and we have yet to have a layout related issue reported to us.

Apple recommends testing on actual hardware always. I really do see their point but at some juncture you have to punt. I don't have an iPad 1, 2 and 3 along with iTouch Rev 1 - 4 and iPhone up to 5. I have already given up testing on each type. As a small shop, I am the only mobile developer, we just don't have a bunch of techies upgrading their phones in lock step with Apple. I don't know anyone with an iPhone 5 at this time. Heck my personal phone is only 2.2. I do have a Jelly Bean tablet.

Tuesday, October 2, 2012

Getting images on the Kindle Fire Emulator

While testing our app on the Kindle Fire Emulator I needed to verify my image processing was working correctly. By default the emulator has no images in the gallery.

Using Eclipse in the DDMS perspective click on emulator-544 in the Devices tab. In the File Explorer tab find the mnt directory and expand it. Find sdcard under than and then Pictures. You can use the "Push a file onto the device" button to copy image files into that directory.

You can also put them in the mnt\sdcard\DCIM directory or the mnt\sdcard\DCIM\Camera directory. The final directory might not exist but you can create it in the File Explorer.

At this point you will need to stop and restart the emulator. It does not appear to rerun the sdcard scanner while running looking for new files.

Make sure when you create the emulator that you enable "Keyboard support" in the hardware section of the AVD or you will have to click on individual letters to type anything which gets boring rather quickly. You can disable this is you need to test with the soft pop-up keyboard.

Sunday, September 30, 2012

Intel Atom emulator crashes with DatePicker

I love the new Intel Atom (x86) emulator for Android development. It starts up quickly and runs at real hardware speeds. I did have one big issue, every time I brought up a view with a DatePicker control in it the emulator would crash to the desktop. Not acceptable.

Running the same code on my phone or in the emulator using ARM worked like a champ. So what should a developer do? This is a bug in the emulator code, not my code. Doing a little research shows that it could be the hardware acceleration at fault. You can shut that off with a setting the android:layerType="software" in your XML file or with a call to setLayerType(View.LAYER_TYPE_SOFTWARE, null); 

The problem is I am developing my app for 2.2 and beyond. That call does not show up until a much later version of the Android platform. Time for some reflection.

Add the following as a new file to your project

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.view.View;

public class NewerMethods {
    private static Method LayerType;

    static {

    private static void initMethods() {
        try {
            LayerType = View.class.getMethod("setLayerType", new Class[] {int.class, Paint.class});
            /* success, this is a newer device */
        catch (NoSuchMethodException nsme) {
            /* failure, must be older device */

    public static void setLayerType(View view, int layerType, Paint paint) throws IOException {
        try {
            if (LayerType != null) {
                LayerType.invoke(view, layerType, paint);
        catch (InvocationTargetException ite) {
            /* unpack original exception when possible */
            Throwable cause = ite.getCause();
            if (cause instanceof IOException) {
                throw (IOException) cause;
            else if (cause instanceof RuntimeException) {
                throw (RuntimeException) cause;
            else if (cause instanceof Error) {
                throw (Error) cause;
            else {
                /* unexpected checked exception; wrap and re-throw */
                throw new RuntimeException(ite);
        catch (IllegalAccessException ie) {
            System.err.println("unexpected " + ie);

Add the following to your onCreate method of the Activity that uses a DatePicker in its view. I have it right after my call to setConventView(...)

        try {
            NewerMethods.setLayerType(findViewById(, 1, null);
        catch (IOException e) {
            // Just doing this on newer stuff to avoid emulator crash
I know, I am using a magic number in the call. I can't use View.LAYER_TYPE_SOFTWARE because Eclipse has no idea about it when compiling 2.2 code.

This allows my code to run just fine in the emulator. I am running 2.2 code in a 4.0.3 emulator as that is the super fast Intel based emulator. I also run the code on my actual 2.2 phone from time to time to make sure everything is fine. Just easier to stick on the computer using the keyboard and mouse while doing initial development and only test on hardware as needed.

Thursday, September 20, 2012

Xcode 4.5 iOS 6 iPhone 5 simulator issues

Last night before I left I begin the Xcode 4.5 official release download. This morning it was ready to roll and then it needed to update a few other areas of Xcode but it was up and running pretty quickly. I then went about the work of having my app make use of the full height of the iPhone 5 screen.

Xcode asked if I wanted to add the Default-568h@2x.png which I allowed it to do. I knew that was one of the requirements so I was very happy it created the all black image for me. Our launch time is super fast so I don't need a real launch image.

Next I knew the rotation messages needed a massage. I add the following lines to all the ViewControllers allowing all orientations to work.

// OS 6 rotate message
- (BOOL)shouldAutorotate {
    return YES;

// OS 6 rotate message response
- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;

I left the original orientation code in place for non-iOS 6 devices. 

Time to tweak the rootViewController

    // Changed for iOS 6
    self.window.rootViewController = self.navigationController;
//  [window addSubview:navigationController.view];

I had to switch to libxml2.2.dylib for libxlm. for my frameworks. Not sure why the newer Xcode has what appears to be an older version of this lib but everything appears to work using it.

I download older simulators (4.3 and 5.1) so I can test as many as possible without swapping devices.

Adjusting the home screen paint for extra size by checking for iPhone 5 resolution and putting our logo below the grid of buttons on the portrait version makes that look nice. Putting extra space between each icon on landscape mode to space them evenly across the screen gives that area the proper look.

All the other screens filled the new height and went smoothly and things look great except for one big issue I have not yet been able to resolve. The back button in the navigation bar does not work in the simulator. Well it does work for everything but an iPhone (Retina 4-inch). I can choose iOS 4.3, 5.1 or 6.0 and any device - iPhone, iPhone (Retina 3.5-inch),  iPad, iPad (Retina) - and everything about my program works just fine. Once I set the hardware to be iPhone (Retina 4-inch) then the buttons will not work. Nothing happens when I click on them, no errors, no highlighting, no action at all.

Seems to me I am not having an iOS 6.0 issue but a simulator issue. Until I get my hands on some real hardware I am not sure what to do. I can install iOS 6.0 on my iPad 2 or my third gen iTouch but that does not tell me if things have gone haywire on a real iPhone 5.

The other area of fun is two of my hardware testing devices are no longer supported by Xcode 4.5. I can't use the second generation iTouch or the iPhone 3G. They are both stuck at iOS 4.2.1. We checked our logs and it appears we still have a user with that flavor of iOS. If I update the software I would set 4.3 as the minimum. Users would either stick with the version they have, upgrade their iOS if possible or buy new hardware. Apple is sort of forcing things along in this area. Even the original iPad has hit the end of its upgrade cycle.

At this point I get to keep digging to find out why the simulator is not letting me press the back button or the menu button I have at the other end of the navigation area on the 4" iPhone. Pretty obvious that I will not even think of releasing a new cut of the program until this is resolved. Sure, the simulator can be hosed as long as the code runs on a real device I will be fine. I really am hoping it is a code tweak to make it work across the board. Right now 4" iPhone information is pretty sparse.

** UPDATE ** Not fixed but I did try rotating the screen in the simulator. The buttons started to work. Then I rotated again and they stopped, then again and the back button would work but not the menu button. At times all buttons will work then will stop working. Rotation may or may not allow them to work again. I really does appear the simulator has an issue in this area.

** FIXED ** I had to open my MainWindow.XIB file, select the Window object and ticked "Full Screen at Launch". Now everything appears to be working on all simulator devices. I need to beat on the application for a bit more but now I at least feel safe checking in the code changes I have made. Hope this knowledge can help out someone else.

Monday, September 10, 2012

Mobile Native vs. HTML 5 - can't hide your JavaScript code

I have the scheduler viewer running in HTML 5. It scrolls around and paints rather nicely. Performance of the HTML 5 canvas control is acceptable on various devices. I had fun experimenting with the Canvas control but one thing really bothers me - anyone can grab my JavaScript code. Sure I could obfuscate it and make it a little more difficult to us but it is still there in your browser ready to steal. A pretty printer will reformat the code to be readable with silly looking variable and method names.

This is just a little sample app so I don't really care too much about this code but what if the code is logging in to your server and making a lot of API calls? Better not do all of that in JavaScript. That means you need to hide things on the server side. Basically you need to move a bulk of the work up there so others can't have free reign on your data. That puts more of a load on your server instead of on the client. We don't want slow clients but JavaScript has really stepped up its processing speed so putting what you can on the client makes sense.

I ran into this situation at a previous company. We wanted to do an HTML interface to our stock market data. Some one looked over the code as it was sent to their PC, figured out most of the API and started grabbing the 20 minute delayed stock market data off our feed. They were not using the API correctly and crashing our server. Going through all the fun of legal was really dragging out so we explain to the thief how to use the API to stop crashing the server. I was not involved in all the legal aspects so I don't know the full story or the final resolution. Given enough time we probably could have gotten the server to not crash and to obfuscate the API even more but that generally turns into a losing battle.

With a Native Mobile App this is much less likely to occur. Yes, you can sniff the wire and try to emulate the calls that way. People will do that. You can use HTTPS instead of HTTP which helps. It really is a lot harder to figure out an API from an App though, you just don't get to see the source code.

This does not make HTML 5 + JavaScript the wrong way to go. This does make you really think about JavaScript if you are accessing a lot of data off your server. If you are just doing an interactive web site, a game or something else where the loss of data is really very minimal and you don't mind others scanning your source code then go for it.

Before you decide HTML 5 is the way to go for a mobile project think about your level of source code exposure. Decide how much you need to handle on the server. Decide what code is harmless for others to see on the client side. Don't go in blind and try to solve these issues the week before your first release.

Thursday, September 6, 2012

Convert Numeric keypad [ENTER] to [TAB] in java

Our data entry staff does a lot of numeric entry. Java uses the [TAB] key to move between entry fields. I was asked if we could have the NumPad [ENTER] key act like the [TAB] key greatly speeding up data entry. I was able to pull it off with a little bit of code.

import java.awt.AWTEvent;
import java.awt.AWTException;
import java.awt.EventQueue;
import java.awt.Robot;
import java.awt.event.KeyEvent;

 * Special event queue to convert NUMPAD + ENTER into TAB
 * @author kevin.peck
 * @date Sep 4, 2012
public class CustomEventQueue extends EventQueue {
    private Robot robot;
    private boolean swapKeys;

     * Constructor
     * Get robot running so we can fake key events
    public CustomEventQueue() {
        try {
            robot = new Robot();
        } catch (AWTException e) {
            System.out.println("Unable to get robot running " + e);

     * @param swapKeys  true to force key swap processing
    public void setSwapKeys(boolean swapKeys) {
        this.swapKeys = swapKeys;

     * @return  true if we are doing key swap processing
    public boolean areKeysSwapped() {
        return swapKeys;

     * Watch for keyevents and convert NUMPAD ENTER key into TAB key
    protected void dispatchEvent(AWTEvent event) {
        if (swapKeys && event instanceof KeyEvent) {
            KeyEvent keyEvent = (KeyEvent)event;
            if (keyEvent.getKeyLocation() == KeyEvent.KEY_LOCATION_NUMPAD && keyEvent.getKeyCode() == KeyEvent.VK_ENTER) {
                if (keyEvent.getID() == KeyEvent.KEY_PRESSED) {

Add this to your main code (class derived from JFrame)
    private CustomEventQueue eventQueue = new CustomEventQueue();

Add this to the constructor or initialization routine of the class derived from JFrame
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                EventQueue ev = Toolkit.getDefaultToolkit().getSystemEventQueue();

Why is there a setSwapKeys() method? So you can turn off this functionality. I set enabled the sample above but in my code it is actually reading a Preference setting. You can enable / disable the [ENTER] = [TAB] at any time in your code by invoking the swap keys method.

If swap keys is enabled I eat the VK_ENTER from the numeric keypad for both PRESSED and RELEASED events. I use the Robot object to send out a VK_TAB press and release on the PRESSED event. Nothing is sent on the VK_ENTER RELEASED event. 

Why am I installing the queue invokeLater? I was not doing that an it ran just fine on Java 1.7 but on Java 1.6 I would get an exception. Putting it on the EDT solved that issue.

So far it seems to be working like a champ. With minimal modifications you can watch for any event you need to perform special actions. Don't go crazy but have fun.

Thursday, August 30, 2012

Common programmer interaction mistakes

Having worked at a number of companies I see the same programmer interaction mistakes made over and over. Maybe if they are brought into the light they can be avoided at your company.

Thinking something is too hard to code

QA, a client, support or any other person who uses the software runs into an issue. They feel like it would be impossible to implement so they never ask. So many times it turns out it is far from impossible and a lot of times it is under 50 lines of code.

Many times you will hear about missing functionality accidentally. Maybe you overhear a hallway conversation or someone in a cube close to you says "I hate this area, why does this button not have a hot-key?" There are a lot of questions that never get asked of the correct person.

The job of our medical coding team is to enter a lot of data for medical insurance claims. I had the chance to sit down and ask them what they wanted to change in the software. One of the big issues was entering decimal places for ICD-9 codes. They said software they used at other companies did not require them to enter the decimal point. Made sense to me so I changed the code to not require the decimal point but to also work if you typed it. This way the data entry did not appear to change to those who are accustomed to typing the decimal place but allowed those who did not want to type it the freedom to avoid it.

I told the project manager I was able to implement this feature and they went off on me. Before I even got to explain how it worked they told me I was breaking the software for everyone else. They had been telling people "No" for years on this request. I screwed it all up. Once they got done with their rant I explained how it worked then the calmed down and said everyone would love it. I went through the same scenario with QA and other staff members, tell them, rant, explain, smiles. It was so ingrained in their minds that this was impossible to do without destroying existing users that we could not do it. There have been many requests for this feature at our user group meetings and via the support ticket system. Of course I did not know about that, I was just told by a user how much easier it would be for them so I implemented it.

Not informing you of repetitive tasks

Copy / paste is available in some areas of the program but not others. Ask if it can be implemented everywhere. If you do a lot of copy / paste maybe you need the program to auto-fill values or if you are doing the paste into another program where you find yourself reformatting or deleting a lot of the pasted data find out if export functionality can be added. 

If it is repetitive and boring then the computer should be doing it for you. Nearly every time I have been asked to do someone else's job while they are on vacation I have found ways to automate the process. In one case a guy I worked with manipulated a Lotus 123 spreadsheet everyday. He was on paternity leave when his son was born. I was a programmer but I was asked to deal with his work too. For some reason I did not find an extra 8 hours in each day he was gone for me to do his job but I did automate it with some Clipper code to run in about 10 minutes time. He came back and found a new job within the company. Did not want you to think I am proposing the use of robots to take over the jobs of new fathers.

Not asking for a feature because only a few need it and they don't want to affect everyone.

The wonderful thing about computers is the availability of settings. Of course we don't all like the same defaults, color schemes, keyboard mappings etc. That is why programs have options screens to configure it to your liking. You need a large font, here you go. Hate the color red, use blue instead.

The other great things about computers is they take care of the boring stuff. Have an Excel spreadsheet you do the same to every day? Automate it using macros! Have a spreadsheet you need to export in CSV format once a week to import into your software? Find out if there is import directly from XLS instead. We do this using Apache POI for our Java code.

Thinking something is easy to code when it has huge system impact

Hopefully this is discovered during sprint planing. At times what seems a tiny feature can impact nearly every table and index in the database. Yes this is the opposite of my first point. Why there is so little middle ground between what a user thinks it will take to do something and what a programmer knows it will take is a big life mystery.

The area to watch out for is always saying "No" to big impact items. If you are doing a 2 month release cycle and something requires 5 months and it will really help the clients then you need to break it into smaller pieces or split a person off with development time to complete the project. You can't just ignore everything that does not fit into a neat little schedule. If you do your program will grow with little incremental fixes but will not GROW with new functionality. Other companies will come along with the missing pieces and take your business away.

Please ask, all the developer can say is "No"

First off your end users, QA staff or anyone who uses the software should never be afraid to ask for a feature. Yes, it might have to make it through the proper channels to be assigned to a release but really the worst that can happen is you are given "No" as the answer. I have seen some many really useful features blocked by the wrong people. People who assume it is impossible or it will break how existing users operate. Unasked questions are rarely answered.

It could be the full solution can not happen right away but it can be partially implemented along with another feature. This happens a lot. If I know a feature is coming in the future I can plan they way I am coding an feature now to accommodate what you need in the future. You never know, it might just come along for free due to some other code I was refactoring. For some reason places find it better to hide all future work from the programmers. Not sure why everything being a big surprise makes them think things will go smoother. I can handle knowing that a feature is for two releases out. If I know it is coming I can make sure any code I am writing now is flexible enough to handle the requests later in the pipeline.

How programmers can help

As a programmer it is our job to do our best not to break existing code. At times we have to write migration routines. We may have to allow the program to run both the old and new way. Settings will be added with the default to the way it has always been. Of course there are times with the old does not mesh with the new. Clients will complain, probably for a few weeks, then they will get used to the new more powerful way. Change just to change is not good, change with clear benefits will pay off.

Don't be dismissive with your end users. Sure, they are going to ask for really weird things that make no sense. Some of it will seem so easy to them they don't understand why you tell them it will take 10 months to code due to current code or database layout. Don't roll your eyes and them and get all technical on why it will be a bear to write. Explain that your initial thoughts point to this being a rather involved process. If they press for why you feel that way give them enough technical details so they can start to understand the complexities.

There are times you are going to mentally block a real solution and even you will think something is a 15 hour project. Later at home when you mind is a bit clearer because you are blasting pixels in a FPS you will hit a 12 minute solution. That can't happen if you did not know the problem even existed. Be open to suggestions always.

Try to find the time to sit and watch the people who actually use your software. It can be in house users or an actual client site visit. They don't always know that they are doing it the hard way. They might not realize there is a hot-key or a "Yes to All" option or another entry screen with just the data they need. Maybe they have never used the export or import functionality. 

It really is not us against them. It is us and them getting the computer to make our lives easier. The computer has no feelings so always make it the "bad guy". Take all the suggestions: good, bad, ugly, freaking weird and keep a physical and mental list of them. Over time you will knock them off here and there making everyone happy. I keep a tabbed text editor open always. I have a tab for each project, one for general notes and one for each platform I work on open always. I end up adding and deleting from my to do list all the time. When people stop by my cube to talk to me I add notes as needed. Too easy to forget little ah-ha moments and I don't want to miss out on anything that will make the software better.

Don't be afraid to fail. There are times I pull a task off the wish list, work on it for a few hours and stop saying to myself "well, I guess I don't have a solution to that". No harm, no foul. Maybe later I will come up with a solution based on my failures. Other times I look at something I typed in a number of months back and a quick solutions hits me, I try it and have success in 15 minutes of coding. That is one of the best coding feelings you will ever have. 

Sometimes I am asking Google about a current issue and part of a post will have a new direction to take on a seemingly unrelated issue. I might cut and paste that into my notes or I might have the time to tackle it right away. I have a lot of code snippets laying about that I have not used yet but am pretty sure I can use in the future.

Monday, August 27, 2012

Experimenting with HTML5 Canvas and JavaScript

I keep hearing about HTML5 especially in the mobile realm so this weekend I decided to see what I could make the canvas do using JavaScript. I have already written the new schedule viewer in Objective C on iOS, Java on Android and Java on the desktop so what the heck.

First attempt was grabbing some sample code of the web and tweaking it until I understood the basics of HTML interaction with JavaScript and basic paint commands for the canvas. I was doing this all via Eclipse and Chrome. I tried to get all the proper plug-ins installed for Eclipse but was not having much luck. I found WebStorm from IntelliJ  and installed that then things became much easier. I could actually put in break points and debug my code. If the code flat out did not run then the basic inspector in Chrome gave me the information I needed to track down those issues.

Again it has been very handy having a multiple monitor setup at home. I can have plenty of space to run WebStorm, NotePad++ etc. on main monitor and Chrome on the second screen where I can test the running application. My second monitor was a free, not super high resolution but still darn handy. Get one if you don't already have one, they are a programming life saver.

Currently I have the following working on the canvas:
Paint time margin (with various gradients)
Paint column headers
Paint grid lines
Paint dead areas outside of grid
Hold down middle mouse button and scroll around in grid

Various "objects" are set up, same objects as in the other implementations. I learned how to get the canvas to resize to fill the screen as you resize the browser. Mouse interactions including up, down, move and exit are in place. I am sure I am still doing various things incorrectly or the hard way but the code appears to be pretty clean and the paint codes runs nice and fast.

JavaScript is very close to Java for general syntax making it pretty easy to adjust to coding in it. You don't have strict variable type checking, arrays and maps have a different syntax but are really easy to use, variable scope is a bit lacking as are name spaces. Most of the code conversion was very straightforward. I can really see where it would be very handy to have a single code base for all platforms from mobile to desktop to OS of choice. Straight Java covers the OS of choice side but does not handle mobile. 

I don't see any painting limitations and the canvas 2D API is feature rich and very fast at painting. I need to chuck the code over on my server and see how it runs on the tablet when I get a little farther along. I also need to tie in the touch events to match the mouse events which should be very easy to do.

Where is will get interesting is in all the user interactions. On the PC you have click, double click, left / right / middle button processing potentials. On a touch device you have tap, double tap and long press. There are times you have to get really creative to handle user interactions. Normally on a touch device a long press will bring up a menu and double tap does a default action (which should also appear in the menu). On a PC a right click shows the menu and double left click is default action.

Still more to learn on the HTML5 / JavaScript side but I am very happy with how much I was able to get done in a few hours this weekend. The web is full of helpful examples and I have dealt with enough programming languages, SDKs and 2D APIs that I was quickly able to get it painting what I wanted.

Tuesday, August 21, 2012

You can't do that!

My job this week was to sit in with our medical coders to find out how we could make their life easier. One of the items mentioned by many of them was the requirement to type in the full ICD-9 code including the decimal point. Other software does not require this as the decimal point always occurs at position 3 according to them. If other software does it then it must not be too hard right?

If fact our FoxPro based product does not require you to type the decimal place. As we convert people from that product to the new Java / Cloud based product this has been a sticking point with them and for good reason. Your data entry staff wants to type the least number of keys possible.

Being a non-tainted innocent comes in handy when programming. I had no background on this issue. I implemented and tested the code in a hour or so. We are using a JIDE shrinkable / searchable combobox table to handle the data entry for this field. As you type the visible content of the table shrinks until it becomes the one matching code. I updated the shrinkable and searchable code to handle everything with and without the decimal point. I also found E codes have the decimal point at the 4th position instead of the 3rd and S codes don't have a decimal point at all. Code a couple of IF statements and those rules work as well. Put in a boolean so you only set this special processing when you are on a diagnosis field and I am done.

I begin to tell people I fixed the issues and they start to have fits! You are going to break all the old clients! I have told everyone you can't have that! The decimal point is right on the numeric keypad, they can type it! Whoa there, I did not break anything. You can still type the decimal point like before, if you skip typing it I do the search with it in the proper place. I handle the edge cases.

People were saying NO NO NO because they only saw one side of the solution. They hit the "it will break others" point and stopped. I had no intention of breaking existing user's data entry habits, never ever considered that a viable option. When programmers are not involved in decisions then this sort of thing will happen. They don't ask the programmer because they have already determined it is too hard or impossible. They will then turn around and require you do something that is nearly impossible that they feel is super easy. Your company needs to have a good feature request vetting process in place. It never hurts to ask but is sure can hurt to not ask.

Everyone has calmed down at this point. They really are happy this feature is in place. Our medical coders are going to be really happy when the new release comes their way in a few weeks. QA will have to get it a solid beating before it is released but the testing is pretty straight forward.

I am ready to move on to the next seemingly impossible issue.

Thursday, August 9, 2012

iPad development to influence my PC code

I am converting the Java WebStart JIDE CellSpanTable based appointment scheduler to the iPad. It has a slightly different purpose on the iPad but needs to display the appointments in almost an identical way. The Java desktop application was recently converted from MigCalendar to JIDE CellSpanTable by me. I was pretty happy with the results but now I am thinking of refactoring it again.

Why bother? First there are some limitations to the CellSpanTable. I am using a JXLayer to get around some of them. That allows me to paint on top of the grid to show the current time line and for Drag and Drop support. Things are a little screwy when I attempt to scroll to a starting position in the grid. When I do that some of the paint offsets are incorrect. I have made all the adjustments in the code to handle this conflict between the JScrollPane and the CellSpanTable.

I also have issues with the time margin not fully painting in sync as you scroll the grid vertically. When you stop dragging the scroll bar everything lines up, just during the drag there is a stutter. This sort to thing always bothers me.

Since I am spanning cells based on appointment durations I can only pick one background color for the full cell span. This means if the appointment starts before normal business hours the spanned cells all get the "business is closed" background color which is not accurate. I also don't get the grid lines painting across any cell that has a spanning appointment.

I have to track extra information for cell spanning and the code is a bit difficult to grasp every time I look at it. I hate code like that. It is complex because it is not an easy process but it is hard to explain why I did what I did to make it work.

When I converted the code to the iPad I did not have a 3rd party grid control to help me out. The nice thing is I was able to concentrate on doing my own grid because I already knew how to do all the other appointment painting, time margin painting etc. I knew all the limitations of the JIDE grid that annoyed me. I was not overwhelmed with the full rewrite of something that I did not fully understand so I could initially concentrate on the grid. In fact I was forced to concentrate on how to get a grid to paint, there was no easy way out. I did some searches on the web just to make sure someone did not have a workable solution but I did not find anything to fit my needs.

I have written many a custom control so I was not afraid to tackle another one. I was able to use Quartz on the iPad to manually paint the grid and all the appointments. I solved numerous issues I had with the JIDE grid while coding the new control. I am fully in control of all the painting. I don't have any scrolling sync issues. I don't have to use an overlay painter - I paint things in the Z order I need. I am not using a grid data storage system that does not completely apply to what I am attempting to do. There are no scrolling coordinate offset issues.

This is not a generic cell spanning grid control for the iPad. This is a highly optimized grid for the purpose of painting an appointment schedule. Not that I couldn't take some time to make it more generic. My goal was to get something running that was super optimized for my painting needs. I want a very responsive UI for this application. I also will convert this to the Android platform in the near future. It should be a fairly straight forward port.

Based on the painting I did on the iPad I have already improved the look of the PC Java code. Taking a second look at things and being under less time pressure I was able to come up with a nicer look to the appointments with the start / end time in a darker color to visually highlight them to the user. I also drew a pointing ball in the margin to visually enforce the location of the current time line that can get a bit lost in the grid especially the current time falls on the hour. Just adds to the professional feel of the app.

I don't have the issue with grid lines not painting as I paint them first then overlay the appointments. The proper background color is painted for the cells too since that happens independent of the appointment paint.

The appointment memory storage is much cleaner because I am not taking what I need and forcing it into the memory layout of the grid so it can ask me to paint the appointments as it is painting each cell. Using Quartz I just paint my layers - verifying that what I am painting is visible on the screen based on paint offset and component size - avoiding all sorts of callbacks and other overhead.

On the PC your scroll with the scroll bars but on the iPad you scroll via touch. I really like the way touch scrolling works on the iPad and I miss it every time I run the PC app. I keep trying to click drag the PC app just like I do on the iPad simulator. Maybe I will have to implement that on the PC too!

Other than the auto-scrolling of the grid as you drag and drop an appointment I think the conversion will be pretty easy. The JIDE CellSpanGrid did the auto-scrolling for me. Not like this is some super secret magic bit of code, just need to write it up and make sure it feels right when it is done.

I am looking forward to tackling this on the PC then again on for Android devices. I am sure I will optimize it just a bit more on each one. The first time you write code it always stinks, you have too big of a picture in your head. On the rewrite you can concentrate on the minutia. You are basically doing a code review of your own work as you convert your logic to each language / platform.

There was a lot of learning around Quartz during this project. Sure I will learn more about Graphics2D under Java too. I have used it enough to have a pretty solid grasp there but something new pop-ups with each project.

Friday, August 3, 2012

Thanks Apple, nice general settings on iPad simulator

For my iPad scheduler app I want to follow the overall settings for 24 hour time. Guess what? You can't set that on the simulator! Under Settings -> General they flat out skipped the Date & TIme options. Why? There is no reason to not have this setting available. I have to do all my testing of time and date formatting on the device itself.

I am trying to be as friendly a developer as possible. If you like 24 hour format then times should appear that way in all your apps. I am used to AM / PM so I generally use that format but Kevin != rest of world.

At least I am not doing a ton of time and date formatting meaning it was pretty easy to test on the device but I should not need to switch to that to test an OS related feature.

An interesting side project that ended up in main project

We are getting PDF files from a client. They contain medical records with one of the items being the patient ID. My initial task was to find PDF parsing code on the web to pull the patient ID from the file then rename the file to include that as a prefix.

A quick search turned up PDF Box from Apache which sounded like it would do what I needed. Grab the download, whip up a simple Eclipse project and I have the text extracted. Very easy to use and understand API.

Of course the next part is where the real work comes in. Have the program respond to command line parameters and if none are provided a GUI is presented to the user. Let them pick the source and destination directories then process the files. Save the last used directories to an INI type file so they don't have to pick the directories every time they start the program.

Once that was working I was told they would really love to have the PDF pages converted to a JPG so they could be imported into our software. Turns out PDFBox can convert to PNG which we can also import. Update the code to handle the conversion. They also wanted to copy the originals of properly converted files to an archive directory. Added that to command line processing and GUI.

I asked since I know now how to use the library to convert PDF to PNG why don't we just import PDF files directly? Sure, why not, do that. I updated the main code base to allow user to choose PDF files along with other image formats. Next I changed the processing loop to handle the page count of each PDF for the import status and did all the code to write the converted pages to the temp directory and then import them as PNG files. All pretty easy stuff and it turns out this is something the clients have asked for over the years.

Before we did not want to import straight PDF files as then we would need a PDF viewer in the code. Adobe used to be pretty good for a C/C++ developer allowing you to embed the viewer using OLE and other API calls but that came to a halt I think around version 9. It has never been a fun task in Java. With the conversion to a normal image format I don't have to worry about any of that. Each page can be rotated, annotated, redacted, etc. using our basic image tools.

Now I asked about the original utility program I wrote. Seems pointless for it to convert the PDF to *page#.png files now that we can import things. This morning I am going to add a checkbox to the GUI and another command line parameter to allow you to control the export of page files which will be off by default. They still need the patient ID extract and rename but probably will not use the page extract. With the code already written it might as well stay in as an option.

Funny how a one off request can turn into something that benefits every customer. There are days you just need to do a little research to find really cool simple solutions to problems. I also got to learn about a new library that may come in handy for other projects. The JAR file is not small but what it does is pretty powerful. We added it as a lazy load JAR to our JNLP file. Hopefully QA does not find any massive issues with the conversion. It worked fine on all the PDF files I tried it on but I know there are a lot of ways for those to be messed up.

Wednesday, August 1, 2012

Jelly Bean on my Xoom

Jelly Bean arrived on my Xoom last night and so far I like it. There are new animations during app transitions, when you have multiple unread emails you get to see the subject of each of them in the notification window and everything seems to be snappier which was the main point of this release.

Install was a ~80meg download followed by the install and reboot. Of course once the machine reboots all can seem snappy for a bit until you run a bunch of apps. I will see how this version does over time. It does look like Google is taking the knocks against Android seriously though. Always tough to fix something without breaking something else. All the apps I tried last night worked like a champ.

I think some of the new transitions happen during certain initialization stages of the app. I watched the USA Today app run a couple of the new transitions more than once which probably means that app is doing something odd that needs to be adjusted. As a programmer I know I have run into this in the past. You don't realize you are doing some initialization twice until you see the screen flicker, a double message in the log file etc.

Curious if they will come out with a version of Jelly Bean for my phone. Might be the thing that pushes me over the edge to root the phone and install something no directly from Samsung. Since Samsung no longer does OS updates for my phone I don't feel bad about doing this or worried that I will screw it up not waiting for an official release.

Wednesday, July 25, 2012

Sharing a keyboard and Mouse between a Mac and PC

My main development box is a beefy dual screen PC. I do a lot of Mac work too. I test all our WebStart Java based code on the Mac to make sure controls are sized correctly, accelerator keys work as intended etc. That is all done with IntelliJ. I also write all the mobile code for iOS devices via Xcode and Android devices via Eclipse meaning I switch around a lot.

I tried VNC for a few days but ran into too many short comings. I have the Mac hooked up to my second LCD and switching video inputs is easy enough but hauling over the mouse and keyboard was annoying.

Yesterday over lunch I picked up a KVM at Microcenter. Box listed it at $29.99 but it rang up at $12.99 at the register. This is the TrendNet 2-port KVM Switch Kit TK-207K. Simple piece of hardware about the size of a deck of cards, just a little thicker and wider. I plugged in my USB generic mouse and MS Natural Keyboard 4000 to the device and plugged in the included outbound VGA (not using) / USB cables to the PC and the Mac. There is a 1 and 2 button on top of the box you press to toggle between machines. If I am on the PC I can hit Scroll Lock twice to go to the Mac but it does not appear to work from Mac back to PC, instead it dims the screen. Press the button is no big deal.

Both machines seem to be happy doing the switch. I can now run everything off the one mouse and keyboard which is making life much simpler. The other big advantage - the MacBook Pro only has two USB ports. I had the mouse in one and the keyboard in the other. I only need one for the KVM switch. This allows me to plug in a USB key, the iPad or whatever without pulling the keyboard.

Here are the minor issues:

1) On the Mac the main screen in the laptop screen. Everything wants to start on that screen even if a program is on the second screen it wants to show pop-ups / associated windows on the primary screen.

2) Just put Lion on the Mac so I could upgrade to latest Xcode. By default Lion does scrolling opposite of what Snow Leopard did. This makes it act like a iOS device which is fine when using touch pad but annoying when using mouse especially when you switch between it and Windows during the day. I turned off that setting.

3) Can't double scroll lock to switch back to PC side.

4) Wish I could run both my external LCD screens of the Mac even if it meant shutting down the laptop display. If that worked I could switch to just using the Mac for email, IM, IntelliJ for Java, Eclipse for Android and Xcode for iOS. The laptop display is OK but not positioned on my desk in a good spot right now. Once you get used to two 24" displays you don't want to go back to a 15" display.

Switched text editors

I had been using PSPad on the PC for the longest time. I then switched to NotePad++ and then after reading a number of glowing reviews of Sublime Text 2 I switched to that. Seems to work out nicely on both the PC and Mac. I had been struggling to find a good text editor on the Mac and was using JEdit. Using the same editor on both machines is very handy.

I tend to leave a text editor open on my machine at all times with multiple tabs going. Right now I have 5 tabs running - Work info, Android Notes, Charge Capture Mobile, Front Office, Tablet Calendar - one for each project I am in the middle of working on. During the day if someone stops by with a suggestion I type it right into the appropriate file. Maybe I come up with some wild idea - type it in. It is my way of keeping massive to do list, future notes, things to investigate and random thoughts all where I can find them easily.

The Mac will take over my Tablet Calendar notes as that is where I will be doing that work for the time being until I start the Android conversion. I also end up opening source code from other projects to steal code snippets so having a bonus text editor open is very handy. Its other big job is grep. Any text editor must have "find in files" to be useful to me.

Tuesday, July 24, 2012

Today's Apple Fun!

I need to test a new app on the iPad. iPad is 5.1x but I was on Snow Leopard and using Xcode 4.2. Can't run the iOS 5.1x SDK on this platform. I got Lion ready to go finally. Had to buy a new larger USB key so I picked up a $9 16GB at Microcenter over lunch.

Run disk tools to create Lion installer on USB key
Lion install went smoothly.
Run Xcode, tells me it is too old. Drag it to trash and it crashes.
Install updates to Lion amounting to 1.84g of download and install.
Still wants to install iTunes update but it fails on two attempts - give up on that.
Try to install free application from App Store - Xcode for Lion.
Wants credit card information, nope, not on a shared work laptop.
Look on web and find you can set up your account under iCloud without credit card info.
Attempt to do that but it wants to verify email first.
Don't appear to be getting email to confirm.
Finally realize it came to my personal account, I have gone round and round with Apple over this and they can't fix it - I log in with my work email but can't associate my work email account to the Apple account.
Confirm iCloud email via link click and login on my PC to Apple website
Ask iCloud to try again but it fails.
Close iCloud.
Open iCloud
iCloud is now happy so I click into manage account and it has a NONE option for credit card.
Update and save info.
Get multiple Apple emails to my personal email about the updates.
Open App Store.
Click on Free on Xcode in search results
Click on Install
Nothing happens
Click on Xcode to move from search results to full screen Xcode information
Click on Install
States Installing... but no status visible
Click on Purchases so I can monitor 1.53 download
Get another email from Apple saying I am downloading stuff and if I did not do that I should change my password. 
Ignore the email.

Run Xcode
Asks to uninstall old Xcode (guess the crash really did fail even though Xcode did not appear any longer in Applications)
Install old Xcode
Xcode runs some extra updates
Xcode up and running and I am able to run the App on my test iPad.
App runs great, scrolls around at full speed.

Try a couple of times to update iTunes and it continues to fail
Search on Google and it is suggested I download the DMG directly from Apple iTunes site
Download 170 meg of iTunes fun
Start installer - asks to close Xcode
Close Xcode - run installer
Installs just fine this time
Run Update checker - no updates found

System is now up to date, well as up to date as it can be with Mountain Lion ready in a few hours, Xcode runs and I can go back to app development. It was a bit of a winding road to get it all to happen though. Felt like way too many hoops to jump through to install the few things I needed to keep working.

Java is not installed by default with Lion. I am now downloading and installing Java so I can use AppCode and IntelliJ to do development. The keystrokes in Xcode are driving me nuts so I am going to switch to AppCode to see how that goes.

Monday, July 23, 2012

Take time out to clean up your program's user interaction

Once a product has been around for a long time you will start to find little issues and inconsistencies. Our app has hit that stage and I am taking the time to fix as many of these issues as I can. It will make the whole thing look more professional. Hey, what about some examples bub?

Double click to Add / Remove

If you have side by side lists / trees on a screen with add / remove or move left / move right buttons people expect to double click on items and have them move between the controls. We try to do this everywhere in the product but missed some cases.

Prompt when an action can't be reversed such as deleting a row

No one wants to accidentally lose data. Make sure they can't without a prompt. This is a super easy fix, just adding a message box above and checking for YES / OK action. Make sure you don't check for NOT CANCEL as clicking the red [x] in the corner is not yes, not cancel but close. Checking for not cancel will have you perform the action which is not what the user meant when they dismissed the message box via [x].

Check for unique names

If users are adding name filters or other similar data to a table make sure they are using unique names. No need to confuse everyone with two filters named Kevin. Do the same check when renaming, cloning or any other operation that allows them to type in a new name.

Enforce permissions uniformly

If you have a permission, privilege or similar system make sure you are consistent in its usage. Don't block them from doing something in one place and not another allowing them to get around the rules. Back fitting a permission system can be a real bear but the users asked for it for specific reasons so make sure you follow through.

Consistent images / Duplicate images

If you use a lock for checked out don't use a door with an arrow in another area. Along the same lines don't have duplicate images scattered about in your directory structure, that will drive your graphics artist nuts and is a waste of install package space.

F1 Shows Help means do it every time

Don't have F1 work some of the time and other times not even if it can't bring up a super specific topic. Have it bring up the general topic for the area you are in until the help team has time to get the specific one ready.

Dirty checking needs to be accurate

When the user chooses to edit some data, they make no changes and hit [Cancel] make sure you are not prompting them with "Changes have been made. Save them?". Verify you prompt when things are dirty and don't bother the user when they are not.

When things take a long time show a progress indicator

During testing with very small data sets everything moves fast. When a user gets hold of the product and starts adding rows a mile a minute initial table requests can take some time. Make sure you are showing a busy indicator of some sort so the user knows the system is busy and not locked up.

Make sure entry fields are wide enough

No one likes to see 5 characters when they generally type 10 or 100. Who wants the zip code cut off at 4 characters? Give them the room they need.

Support spell checking consistently

You finally added spell checking to your free form notes fields. Awesome, not add it to all of them not just in one part of the system. Users expect spell checking to work everywhere: email, IM, search text entry, etc. If ;you start providing it then finish providing it.

Pick a date entry control

Is it month / day / year or year / month / day? Is it a combobox? Can I pick or type? Does it support a short-cut key for today? Use the same format and entry style everywhere.

Use human Boolean strings

Programmers say True and False, humans don't. Use Yes / No and make sure you descriptive label is not a double negative like "Don't erase file at end of processing: NO". People don't like to scratch their head figuring out what you mean.

Term consistency

Don't call it a privilege here and a permission over there. If a menu item invokes a dialog have the dialog title be the same as the menu item so when support gets a call stating they are on the Update Patient dialog you know they got there from the Update Patient menu item. Please don't have the "..." in the dialog title though.

Don't allow crazy entry into specialized text fields

We all know to dollar amounts numeric only but what about illegal file name characters? Anything you DB of choice hates? SQL injection? Limit the users typing as much as possible or at least show a message when they press [Save] to let them know something is amiss.

Don't over prompt, show all possible errors / warnings

No one wants to fix issues one at a time. If 4 of the 6 entry fields have invalid data then tell them about all of them in your first message. Don't make them fix one then complain about the next one until they have fixed all the issues. Think how much fun this would be is your compiler stopped on the first error.

Put errors / warnings in a scrolling list at a certain size

A huge message box that does not even fit on the screen does little good. Some errors snowball into more errors. Put a reasonable limit on the text you show but let the user scroll through all the text. The key to fix 90% of the problems might be on the final line.

Don't call your user an idiot

Face it as programmers we tend to think in the negative. This failed, the build is broken, fecal matter has impacted with the spinning cooling device. Programmers tend to use negative language in their error messages. Try to avoid that. A good tech writing team will keep it from happening but programmers tend to put in the placeholder text and a lot of time it will make it into production. Don't get all sappy and just sprinkle in "Please" and "Thank You", actually work on the wording.  "User name is invalid" can be "User name must be unique" "User name has invalid characters - allowed characters are xxxxx". Try to be helpful and point them in the direction to fix things instead of just telling them they suck.

Use reasonable column widths

Zip codes don't need 50 characters of width but descriptions do. Try to show all the information in a cell if possible but it not make sure tool tips work. Users don't want to click on Edit just so they can see the values in a dialog box.

Resizable dialogs anywhere it is possible

Most of us have used MSCONFIG at some time to find out what sort of crap has decided it needs to run every time our machine starts especially when you are looking at a relatives computer which under the gun to "just make it work like it did before". Why is this dialog not resizable? It isn't because that was a bear to do in C/C++/MFC. Most of use probably don't have this excuse anymore.

Feel free to let me know about your favorite issues to address.