Friday, September 27, 2013

Finally I get to do a tablet only app

We have a dashboard style web page used by our clients. I recently converted the charting side of that from flot to HighCharts. HighCharts gives much nicer looking charts by a long shot and the price was reasonable. All of that work was in JavaScript which I must say I don't miss and am very happy to get back into the mobile side of things.

JavaScript is just barely acceptable on an iPad or Android Tablet. Yes, I tweaked various UI aspects to make them more touch friendly but if we want to be able to look a client in the eye and tell them we have a dashboard that works on their tablet we need to go true native mobile.

All the code I have done in the past has been universal phone and tablet. For this type of dashboard we are going to start tablet only. We really want to design to use the space available. Of course 1024x768 (older iPad and iPad mini current maximum) is not a ton of space but it is what a number of folks run on even older desktop PCs if they only have a 15" LCD.

At this point I am sketching out ideas and have started a framework on the Android side. I am going to start there as this seems a perfect fit for fragments within an activity. Previously I have used fragments to learn about them and knowing it is the proper way to approach the future. Now I will get to exploit so much more of their power. I have not had the need to swap in one fragment for another or to add new ones to an activity, I have only defined them in the XML and let them operate as is.

Since this will target 3.0 and above on large devices I don't even have to worry about the compatibility library. Nice to get to be able to fully use the newer API features.

I am using achartengine for the pie, line and bar charts on the Android side and core-plot on the iOS side of things. The current smaller app just displays a pie chart so I will need to learn my way around the others.

Not sure what approach I will take on the iOS side of things. There is nothing like fragments there so I will get to deal with UI views and manual placement of things. This is why I plan to get it up and running on Android first so I can knock out the initial design without fighting layout issues. I should be able to figure out a number of UI patterns such tab controls, menu options, widget manipulation buttons etc. and run them by beta testers before I begin the iOS conversion.

Thursday, September 5, 2013

AAAARRGGGG iOS layouts stink!

I hate iOS layout management. Yes, everyone loved it when you knew the iPhone had this one resolution and you could perfectly layout everything. All phones were held in portrait only mode. Even the auto code generator blocked landscape by default. We knew what you had and how you would use it so just shut up. All Apple devs told Android devs they were hosed with their stupid layout managers without true WYSIWYG editing. Na-na-na-na-boo-boo.

This meant if you wanted to support landscape you added code to move things around and resize them during orientation changes. You could still use IB to see that pristine portrait view. Then came the iPad which was used in landscape a lot. Just do IB in that mode.

Well IB sucks. Adding storyboards just allowed it to suck in some new ways. Sure you can tie you portrait screens together and you can do separate iPad and iPhone screens but you have to manually tie all the controls back to your source code with crazy Ctrl + Click drag and drop if you can get the right source file to appear in a squished down window below the stupid layout that is way too damn big for iPad screens that wants to constantly scroll and resize every freaking time you click on it!

You are an idiot - use auto layout. If you don't then you are hosed. But Apple did not backport that, you had to wait until most users were on iOS 6. Google backports, Apple does not. Apple is a jerk in this area. iOS 6 seems like a safe enough target at this point.

Auto layout has a new set of issues. IB really blows here. It has to have everything in perfect order even though when you are creating the layout you can't get it in perfect order until the layout is fully loaded with all the controls. They IB rewrites the damn file over and over. You lose the battle every single time wasting a huge amount of effort.

So screw IB, it has been screwing you. Besides if you want a team working on things they can't all have the storyboard open because version controls DIFF is nearly impossible. It is a SNAFU. Time to write it all in code and skip everything related to IB.

You have a couple of choices. Use the auto layout weird ASCII stuff, which is just ugly to read, or use NSLayoutConstraints manually. I think I am going NSLayoutConstraints. If I am getting no WYSIWYG support I might as well take full controls. That ASCII stuff is too bizarre. Honestly this all feels like I am moving back into the land of GridBagLayout in Java.

GridBagLayout was the end all do all layout manager for Java back in the day. Yes, I did some crazy layouts with it that worked and even allowed you to resize the panel and flow properly. The code was ugly and not maintainable. You could not look at it and tell what the hell was going to display on screen and you could not add a new control between other controls without totally screwing everything up. I worked with developers that used GridBagLayout for everything even though a simpler BorderLayout would have worked. Use the right tool for the job people.

Look Apple there were a ton of other good examples of how to do things. MigLayout for example if you only want one layout manager. The Android XML way of doing things if you don't might multiple layout managers that deal with each other. At least with Android you can layout portrait and landscape and just put them in different directories. There is a WYSIWYG viewer too. I use it to preview the code changes I make in XML and so far have been able to build every layout I have wanted. The Android side is not perfect but is better than what I have seen from Apple.

Nope, Apple just puts all of that on you. Now I get to manually code all this crap and other devs will be able to see what it looks like when they run the code.

I just wanted to convert a current screen from a table view to a normal view. The original developer misused a table view for the screen and I need to clean it up and give a better look. IB does not like it when you try to change view types. Time to punt. Yes, I am using Xcode 5.x and I know it is supposed to have better auto layout support but it is still a mess.

Having spoken to my other iOS developer friends they have all stated it is time to move as far away from IB as possible. It has done nothing but screw them over. They think I am a fool for attempting to stick with IB as long as I have. I really just wanted to get the current project off the books but that is not going to happen. I can try and blow away the current table with a normal view then reattach the segues to the new view and leave it at that but that seems a new waste of effort.

I am going to have to learn auto layout. It is the new Apple way of doing things. It is the only hope if Apple decides to ever come out with a new resolution, which I really think they should. People are expecting HDTV on their devices. 1024x768 on the iPad mini is not cutting it anymore.

Maybe someone will come out with an excellent layout manager for iOS that will solve a number of these issues. At this time I don't care about WYSIWYG at the start. Something that is easy to code and maintain is what I want. I enjoyed working with MigLayout. I converted over 300 Java desktop screens from old NetBeans format to MigLayout at a previous company. I find the Android layout managers more difficult that MigLayout but still serviceable. The new Android Studio does a really nice job showing me a preview of my screens as I edit the XML. The layouts work and scale on various device sizes.

Done with my rant. Off to code NSLayoutConstraints.

Wednesday, August 28, 2013

UITextField Change made by Apple

The following worked prior to Xcode 5 + iOS 6:


@property (weak, nonatomic) IBOutlet UITextField *source;

if (![self.source.text isEqualToString:@""])

It now needs to be

if (self.source.text != nil && ![self.source.text isEqualToString:@""]) {

Previously if the user never touched the text field you got back an empty string. Now you get back a nil string instead. 

Just found this while testing code I am updating for iOS 7 while running on a device under iOS 6.

Shown for simplicity. In the actual code I am using a utility method to trim the string and check for a length of 0. The stupid trim method for iOS is a super long line and can be found all over the web as everyone must write it over and over as Apple does not include it in the base NSString object.

Tuesday, August 27, 2013

Finally have new ActionBarActivity working with Android Studio

Yes I am a sucker for punishment. The new Android Studio 0.2.6 came out today and I found this out my usual way - saw it on Reddit. Since I just battled this beast yesterday I thought I would give it yet another shot.

Post install it still could not build my project but was mad about even more things. I decided to delete the entire project off disk and start fresh especially since it kept being mad about gradle build settings and make settings that I would change and save and it would forget I had done that.

I deleted the project. Started AS, told it to create a new project with old project name, single activity. While it did this it appeared to download some additional gradle files. Probably updating from 1.6 to 1.7 but I am not sure. It did not do that when opening my old project.

Shut down AS. Copied the java source code, resource files and manifest over from the working Eclipse project. I did not want to risk changes to a working project. Started up AS and it found all the files automatically. I love that about Java, just put the files in the proper directly and have at them.

Copy in the build.gradle from this web site http://www.recursiverobot.com/post/59267986367/setting-up-the-new-actionbarcompat-in-android-studio then add the dependencies to the two bonus libraries I am using - achartengine and GSON. Run the rebuild all and everything worked like a champ. No errors. I was able to deploy it to my Note II and it ran perfectly.

Obviously multiple things happened here. AS was upgraded and it needed to upgrade various support tools which it did not do until I forced it via creation of a new project. That is pretty annoying. Once that was in place it is finally working.

I am glad they fixed the issue dealing with Google support libraries. The actual editing you do to the build.gradle is simpler than the project import work I had to do in Eclipse. You can read those steps here http://developer.android.com/tools/support-library/setup.html

Do I think this project will keep working? Who knows, seems on the AS side of things they make changes that require you to start with a fresh project or you are hosed. Gradle is in flux too. I like the editor and layout preview features of AS so I may use it for the next parts of this project. I really want to come up with functional tablet layouts beyond what you can do on the phone. I have everything split into fragments so this should be possible. I also want to use more than just the pie chart from achartengine and have more than one chart on screen in tablet mode.

This ties back into the JavaScript work I was doing in another area of our product. While that works in the browser on tablets it is slow and cumbersome. I should be able to do something similar in native code with large gains in speed and usability.

Using Genymotion to test against various device sizes. Nice and fast and recommended when you are not testing on an actual device. Very happy they added device rotation support.

Monday, August 26, 2013

Converted from ActionBarSherlock to new Android compatibility library

Since I was never able to get ActionBarSherlock (ABS) to play nice with Android Studio (AS) I thought I would convert to the new blessed by Google Android Compatibility Library and the ActionBarActivity.

Of course that did not work out as planned. I finally gave up on AS and just got it working in Eclipse. I tweaked the code and add an action bar menu item, setup a new base class and did some code clean up. It all works great. I guess I need to try it all in AS again but it gets so frustrating. I really like IntelliJ and there are some cool features I am missing by sticking with Eclipse but AS just is not right in the head when it comes to working with 3rd party libraries you need to import as library projects.

Some are now saying "Yeah, the IDE will show an error but it will run on your device!" Look, I hate warnings in my code and tend to turn as many of them on as possible so the IDE catches as many stupid mistakes as it can. Now to have an outright error everytime I build? No thanks.

I do like the new compatibility library. Got rid of the word Sherlock from various areas in the code so it all looks more native and cleaner. I have missed working in Android land and with a little break in the action I have been able to sneak back in there to do some minor tweaks to our app.

My plan is to get it all working in Android Studio so I can use the best of both IDEs. Prior to ABS and now the compatibility library I was not having any issues doing that.

Friday, August 9, 2013

JavaScript and Highcharts

When you work at a smaller shop you get introduced to a lot of technology and you pretty much have to go with the flow. For the past couple of weeks that flow has been down the white rapids of JavaScript for me.

The goal of the project was conversion from flot to Highcharts. Flot offered some very basic graphing and they wanted more eye candy and functionality so they decided on Highcharts. Will cost the company a licensing fee but it will be a much more professional product in the end.

I have not done much JavaScript in the past. I know it is not Java but the syntax is very close so getting up to speed on that was not an issue. Figuring out all the nuances is another story. I have the project up and running now with some final polish so it works better on iPads and Android tablets.

This would be considered a small project. Single page with two tabs. The page contains a dashboard layout control and you can add widgets. Each widget has associated HTML, shared CSS and a JavaScript to query for the JSON data and convert it into Highchart format. We have all the fun of formatted tooltips and configuration settings such as legend position and visibility of data labels.

So where does the fun begin? The whole code / debug cycle is a bit frustrating. I am using Eclipse and Chrome. If I just change a JS file I can save it in Eclipse, hit refresh in Chrome and see the results. If I am changing CSS or HTML I get to clear the cache in Chrome then refresh to see the changes.

Chrome has a decent debugger but you have to make sure you include the JS in the proper file for Chrome to see it as a source file. I had to remove it from a styles.js and move it into a controlling HTML for this to work. Then the break point may or may not work. You end up doing console.log(object) and then just sniffing around in the output console to see what is happening.

Don't forget console.log('Widget is ' + widget); is totally different than console.log('Widget is'); console.log(widget); The first one converts widget to a string which is generally useless. The second set of lines will show widget as an object you can inspect.

JSON.stringify(object) can come in handy at times. You will get circular references for core objects but for looking at return values from the server and what not it works fine. I usually copy that output into Sublime Text 2 and run the JSON formatter on it to get a good look at the results.

Since JavaScript is not strongly typed Eclipse is not a lot of help when it comes to finding variables and methods. You just have to know what is there by opening code and looking around. Not the best way to be productive. You also are not told your code is crap until you run it. I know dynamic languages have their strong points but I really missed this area of strongly typed languages.

Scoping is another bit of fun. If you want to trigger an event from one place and catch it in another, well it works but figuring out the proper scope can be a bit of a pain. It is all up and running but I ended up getting a lot of help from a developer with a stronger JavaScript background than I. In the end I was still unsure why what he handed me worked but I was just happy it did.

Highcharts is a really solid product. I am very happy with its final look. I was able to pull off a number of cool features. I did a lot of web searching to find out how to format tooltips, grab events, set up gradients, use multiple y axis, do stacked bars, etc. It really helped to be able to run jsFiddle sample projects. Guess that is one of the nice things about JavaScript, you can piddle around with it on a webpage before you toss it into your project.

Friday, July 12, 2013

Trusting the API is not a good idea

You are programming right along and need to accomplish what appears to be a simple task. You look at the API used by the company and find a one line call to do what you need. Make the call, get the expected results and move on to the next task. All rainbows and unicorns right?

Not so fast there bucko! The key word here is fast. The method I called did do what it needed to do and returned nearly instantly because I hardly had any data in my test database. Once you had a large amount of data it was painfully slow as we found out when attempting to run it at a client site. I had no logging output around the call as it was never an issue for me. It just looked like the program froze when running at the client location.

When something breaks I blame myself. I figure it must be in my code. Took another developer looking over my shoulder to point out "That call might be slow". I had looked past that line over and over again. Of course when I ran the program it sailed right past that line so I never thought about it. I was blinded to it because I was sure I was the one to blame.

We were able to have the client run another command against the database to clear out some old data to get them past that point. We then found the next step, again relying on the API, was also very slow but I had logging in place to watch that progress.

Time to rethink how all of this needed to work. We fixed the initial call to work in a reasonable amount of time and are in the process of gutting the code to write records to a file which we will then import via "copy {tablename} from {outputfile}" x 4 instead of doing inserts in the code. We were able to import 1.2 million records in 1 minute and 46 seconds using the 3 copy calls where it was going to take days to do it in code one insert at a time while parsing JSON streams.

This particular client has a much larger dataset than any other client. We are talking to a 3rd party vendor to get the 8.2 million records that need to be inserted via JSON requests. After these code changes things will run faster and scale better for every client. My part of the code is the JSON to our database format conversion. So far that appears to be working properly at least.

I made the mistake of trusting the existing API calls. I have only been at the company for 4 months meaning I had no background in company lore. I had no ideas what areas had bitten folks in the behind in the past and I figured the every call was optimized. Trust no code especially "this one line can't do much or take long". I should have put logging messages above and below the API call so I could have spotted this in the client run quicker. We knew up front they had a ton of data. We knew we did not have a large sample for testing. This is where extra logging is really helpful.

Lesson learned. I hope I don't make it again.