Rapture in Venice

:: Mobile Design and Development Shop specializing in iPhone, iPad, and Android

wdf-carousel
pholium-carousel-flat
Movementum
finds-carousel
spec-hd-carousel
aa-carousel
passtouch-carousel
tasklist-carousel
ss-carousel
fuzz-carousel
wwp-carousel
kindercards-carousel
hoya-carousel
<<<   |   play   |   >>>

The Horrors of Sub-Contracting

I’ve been a full-time mobile consultant now for three years and, even in that short period of time, I’ve seen the kind of work I do change a lot. When I started, I did a lot of projects for budding entrepreneurs and fixed-bid work. I loved it! But over time, partly due to the allure of a high (and steadily rising) hourly rate and the cold reality of an App Store not making many millionaires anymore, I’ve found myself doing a lot more corporate work.

Contract work with big businesses comes in a couple of forms: hourly work and sub-contracting. Hourly work is usually working on a company’s app product line or creating a new app for them. Sub-contracting is the kind of work you get through bigger mobile shops who need to augment a project team with a mobile specialist like I am.

One such gig has made my 2014 a nightmare and I wanted to share that experience with you.

The Opportunity

Back in October 2013, I was approached by a former co-worker of mine about re-writing a pair of mobile apps (iOS and Android) for a company he was working with. This is on behalf of a local Denver firm I won’t name. The apps were small and simple and I had some time available so I told him I’d do it. I bid on the project, but 2 months later the project still wasn’t ready to go and I had to back out because my schedule had filled up by then.

A month later and things were just then ready to go and…hating to pass up paying work…I decided to go ahead and do it. There were some warning signs, namely the length of time it took to start the project, but I really wanted to re-write these apps.

I should have said no.

Turbulance on Takeoff

It’s now January 6th, almost 3 months since I was approached about the project, and here we were at the kickoff meeting. So nice to get this going! Now, my contract reflected the expected timeline; this app would be done by the end of March. Unfortunately, this is also when I learned that neither design nor services had been started yet. What was going on during those previous 3 months??

I had cleared 2 full weeks in my schedule to get things going, but I was going to have very little to do. I toyed with app architecture and tried to make what I could of the early wireframes. A couple services popped up, but it was not even a week in before I was already stalled. I’d started with the Android app, and wanted to complete it before moving on to iOS, but to heck with it…I decided to start the iOS app while I waited.

Soon thereafter, I abandoned working on the apps full-time and would come back to them when the services and designs gave me more to do. I’d pop in for a day or two, a night here, a couple hours there. I’d be working on the apps twice a week, then once a week, then not at all for weeks, then a few times a week, then not at all again.

I’m ashamed to say, I am still to this day working on this app. It’s September 18th, over 8 months since it began.

The Fundamental Problem

I’m an experienced consultant. I’d done part-time consulting for YEARS before I went full-time. I know how to handle a client, so what went wrong? Why is this project taking so long? More alarmingly, the iOS app has long been abandoned! I’m still trying to finish just the Android app! (I stripped out the iOS version of the app from my contract and it won’t be done by me. All the hours spent on the iOS version were wasted.)

What went wrong? What. Went. Wrong?

The problem is my client isn’t a client. They’re a firm, and they’re the ones working directly with the client. I have no managerial responsibility on this project, I am simply the “mobile guy.” And for reasons I cannot even begin to fathom, this firm has allowed their client to drag a simple project out for 8 months:

  • The client spends weeks before they’ll make a decision on…anything.
  • The client approves wireframes and then, later, wants wholesale changes.
  • The client wanted a totally new app design, but slowly reverted every design decision back to the “way it is now.”
  • The client doesn’t answer questions until they’re asked 12 times.
  • The client is clearly insane.

      None of these things are new to me. I’ve worked with dozens of clients, and I’ve had to fire a few of them for being, quite frankly, shitty clients. Once, I fired a client because they had just fired their designer for the second time and they wanted a whole new app design (for a second time). I told them to keep their 2nd payment and I’m done. Another time, I ran away from a client because I had 10 different roles and had been given no authority for any of them.

      Bad clients happen. So what’s the problem in this case? The problem is…it’s not my client. I’m at the mercy of a firm that has mishandled the client in every way imaginable. They’ve allowed the project to stretch to absurd lengths. They’ve allowed them to constantly change requirements with no change to the contract. Quite frankly, the PM can’t manage this project.

      Why am I still working on it? Because I’m loyal to a fault. Also an idiot.

      Outcome

      Loyalty has its limits, and I’ve just now informed my friend that I will cease all development next week, whether the app is published or not. I didn’t want it to come to this, but despite the app being all but done I still think things would drag into 2015. What a bummer New Year’s woulda been. I think I’ve been way, way, way more than fair in all this. I don’t think more than one or two of my contractor buddies would still be working on this thing. And what’s frustrating is it’s not a project that’s a tech failure, or that it’s too buggy, or that it’s just taking too long. No, it’s simply that the client has no idea what they want, they have no urgency to get this app done, and I’m powerless to effect them as a sub-contractor.

      Let this tale be a warning about the horrors of sub-contracting.

      • Print
      • Facebook
      • Twitter
      permalink

      ,

Getting the Charles Debugging Proxy to Work with iOS and Genymotion

The Charles Web Debugging Proxy is a near mandatory tool for any developer. Getting it to work with your desktop apps is usually very easy since it just…works. However, for use with mobile, there are a couple tricks.

Configuring for the iOS Simulator

The iOS Simulator is a native app that “imitates” your iTouch device. Because of that, the only configuration you need is to install the Charles certificate. You can do that by downloading and running this special script on your Mac. (There’s no Windows configuration for this because you can’t run the iOS simulator on windows.)

Restart Charles and your simulator to be assured of a working connection.

Configuring for Genymotion/Android

We’re going to ignore the official Android emulator because you shouldn’t be using it anymore anyway. So, we’ll use Genymotion for this example. Since it’s a virtual machine, and not native, you need to relay the network connection to your local machine. If you don’t, Charles can’t see the internal Genymotion network and none of the requests will be seen.

First, we’ll need the Charles certificate:

  1. Download the Charles certificate for Android.
  2. Unzip and drag and drop it on to your running Genymotion device.
  3. Run the “File Manager” app on your Genymotion device and open your Download directory there.
  4. Tap the certificate to install and name it however you wish. (You may be asked to set up a security code first.)

With that done, now you need to configure a proxy to get the network traffic running through your desktop. Follow these steps exactly:

  1. Open Settings and tap Wi-Fi to see your wireless connections.
  2. You should see something like “WiredSSID”. Tap and hold it until a menu appears.
  3. Select “Modify network”.
  4. Change the “Proxy settings” to Manual.
  5. Change the “Proxy hostname” field to 10.0.3.2. This is a special Genymotion IP address so don’t try setting it in the original Android emulator. It won’t work!
  6. Change the “Proxy port” field to 8888.
  7. Tap Save.

    Restart Charles and Genymotion to be assured of a working connection. And remember, you’ll need to perform these two operations for every new Android device you create because they’re all physically separate.

    If you now run an app you’ll see the network connections appear. You’ll still have to configure SSL settings to see encrypted traffic, but that’s explained clearly in Charles and is up to you.

    Go forth!

    • Print
    • Facebook
    • Twitter
    permalink

    , , , , , , ,

Speeding up Android Studio

I’ve been using Android Studio for about a year now, adopting it early to get a jump on things. And in that time, I’ve certainly had my share of frustrations with it, but it’s going to be a superior tool to ADT when it comes out of beta, so it’s worth it to use it now.

Here’s a few tips I’d like to share with you if you do plan on using it.

The Command/Control-E Menu

I use many IDE’s, from XCode to Sublime Text to Android Studio, and I use each one differently when it comes to file navigation. In XCode, for example, I tend to toggle the “Recent Files” option a lot so that the Project Navigator is only displaying the files I’m mucking with at that moment. In Android Studio, though, I use the Command-E menu.

Open up a bunch of files in Android Studio and then press Command-E (Control-E on inferior OS’s). You’ll see something like this:

You’ll see two columns. On the right are your most recently opened files, in descending order. You instantly have keyboard access so you can arrow up or down and press Enter to open the file you want. This is extremely handy and the optimal way to move between files in Android Studio I think.

As a bonus, on the left you’ll see a list of views you can open. This is also very useful for navigating around the IDE itself, but I encourage learning the individual keyboard shortcuts for them as that’ll be faster. Start with Command-6!

And before we continue on, you might be asking why not just navigate using the tabs? You can do that, yes. However, I find it slower, especially with a mouse. Even with the keyboard, it’s a three-key combo by default. The Command-E popup really is the fastest way to navigate…give it a try!

Avoid the Wizards

Android Studio improves on ADT when it comes to wizards that create activities, resources files, etc. for you. They are more detailed and provide more options. There’s only one problem: you shouldn’t use them.

Well, that’s not totally true. Sometimes I use a couple of them early on in a project, but I still suggest to avoid them after that. Why? Well, several reasons:

  • You should be creating a lot more fragments.
  • You shouldn’t be creating many activities that actually do anything.
  • You can’t avoid creating menu XML for each activity.
  • It’s faster not to.

Do you put all your logic in activities? You really shouldn’t. For the most part, you should be creating “shell” activities that do nothing but host a fragment for your phone-form views (or multiple fragments for your table-form views). This leaves near-empty activities in your code and, rightfully, puts that code in fragment-land!

So, why not use the wizard? Well, the wizard wants to create activities for you, not fragments, and that’s wrong. So what I’ll do when creating a new screen is to clone a previous screen from the bottom-up:

  1. Copy and paste the fragment XML from a similar screen. (Enter new filename.)
  2. Change the XML to match my screen requirements.
  3. Copy and paste the fragment class from that screen. (Enter new filename.)
  4. Change the code and handlers for my screen requirements.
  5. Copy and paste the activity class from that screen. (Enter new filename.)
  6. Direct that class to load your new fragment.
  7. Add the activity to the AndroidManifest.xml. (Or crash!)

A bunch of steps, but it’s many times faster than using an activity creation wizard. Plus, you’ll have to create your fragment yourself and re-jigger everything anyway. If you’re like me, you have a base activity that simply loads a fragment and your fragment logic always looks similar. Same for resource files.

Copy and paste is your friend…well…this time!

Genymotion

There’s no argument. You must be using Genymotion for Android development. Why? Oh, well for one thing you won’t have to wait around for an hour for your simulator to load, and you DO need simulators to test on various devices so don’t tell me to just use a device…plus, it’s nice not having a phone wired to your computer all the time, and Genymotion runs so fast and smooth and, yes, yes, I know there’s that Intel thing to make the real simulator faster and that works (after an hour of trying!) but you still have all the other problems like when you run the app and the simulator comes up and it never runs your app because it’s freakin’ disconnected and it sometimes takes forever for the app to run anyway and WHY THE HELL CAN’T GOOGLE GET THEIR SIMULATOR RIGHT ANYWAY!!!?!?!!

OK, let me breathe.

Alright, so yeah, use Genymotion. It’s not only a way better environment than Google could ever provide, but it’s super simple to install, too! (Which you wouldn’t expect from a “virtual” environment.) All you need to do is install Virtual Box (hell, you don’t even need to run in, just install it) and then install Genymotion. You’ll be shown how to create your virtual device and…oh man, it’s just so easy. Android Studio sees Genymotion as just another device like the simulator or your Nexus. It’s awesome.

And to make launching Genymotion easier right from Android Studio, there’s even a plugin.

This isn’t even a recommendation. Go get it. Stop arguing.

Download Everything

This one doesn’t really just apply to Android Studio, but I’m including it here anyway.

Download everything Google offers you. Every SDK. Every bit of sample code. Everything. Do you only use SDK 10 and the latest stuff? Whatever…just download everything!

There’s a lot of reasons for this. For one, you’ll open existing projects that will fail because they use a different SDK. You will inevitably be testing against different devices in the future. Have you considered Kindle? So, when you install Android Studio and need to download what you need to use it, do yourself a favor and just get it all now. It won’t take that long and it’ll be way better than stopping multiple times later.

DOWNLOAD ALL THE THINGS!!!

  • Print
  • Facebook
  • Twitter
permalink

, , ,

How to Create a Flappy Bird Clone with SpriteKit in 20 Minutes

First, create a project in XCode. We’ll call it “Floaty Avian.” Next, bring in the SpriteKit and…

WHY ARE YOU READING THIS? WHAT IS WRONG WITH YOU?? THERE’S A MILLION GREAT GAMES ON THE APP STORE, AND YOU’RE **STILL** HUNG UP ON THIS ONE? IT’S GONE. YOU’RE AN IPHONE DEVELOPER! I CAN’T BELIEVE YOU CLICKED THIS LINK! YOU REALIZE IRRATIONAL GAMES WENT OUT OF BUSINESS YESTERDAY, RIGHT? GO PORT BIOSHOCK! FLAPPY BIRD? YOU CAME HERE TO REMAKE FLAPPY BIRD?!

WHAT WERE YOU THINKING?!

  • Print
  • Facebook
  • Twitter
permalink

How to Memorize Block Syntax

Since block syntax came out alongside iOS 4, I’ve struggled to memorize it. Sure, blocks without return types or parameters = ^{ return @”super easy to recall”;}, but once you factor in arguments and want to accept a block argument in a method, thingsBecome:(CGFloat (^)(NSInteger way, id more, CGRect complex))dontYaThink?

It’s no wonder that Fucking Block Syntax has become one of my most beloved websites.

But if you’re not the Rain Man and, like me, have trouble remembering the syntax accurately, there’s hope! I have a full-proof way to memorize it.

The Two Basic Forms

There are two basic forms to memorize. The first is when your block has a name, and the second when your block is a value (anonymous):

  1. NSInteger (^myBlockName)(CGFloat param1)
  2. ^NSInteger(CGFloat param1)

Take a minute to look at these two forms. The first form is as normal and expected as could be. REMEMBER, put the block name in parenthesis. If you do that, it’s easy pickings. The ^ is like a * if the function was a pointer. Just remember those parenthesis. Visualize how the parenthesis cuddle the name of the block. Think: Cuddle The Name.

The second form is ridiculous. Backwards almost. Since there is no name associated with the block, the return type flips to the other side of the carat. No cuddling needed, either. Clearly, tho, dropping the name means we can compact the syntax. I like to remember the phrase, Flip No Cuddle. To me, we flip the side of the carat the return type is on and lose the parentheses.

Apply It Everywhere

With these two concepts in mind, the named block and the anonymous block, let’s see them all applied. Read the following sample code and identify each one, repeating the above phrases as you see each one. Recognize if the block is named or not, then say either Cuddle The Name or Flip No Cuddle:

// pass block to method
[self makeNumberFromString:^NSNumber *(NSString *str) { ... }];

// define block locally
NSNumber * (^local)(NSString *str) = nil;

// property
@property (copy, nonatomic) NSNumber * (^myProp)(NSString *str);

// the defined method
- (void)makeNumberFromString:(NSNumber * (^)(NSString *str))named {
    ...
}

How did you do? Your answers should have been Flip No Cuddle, Cuddle The Name, Cuddle The Name, and WHAT THE F*** ARE YOU KIDDING ME? Yep, sorry, method parameters bend the Cuddle The Name mold a bit by flipping the method name to the outside. However, this too is easy to remember because the carat remains and, hey, ALL method parameters put their name on the outside. Right?

- (BOOL)textFieldShouldReturn:(UITextField *)textField { ... }

So, just put the whole expression in parens and the parameter name on the outside like you always do.

Typedefs? Cuddle The Name!

I’m not a huge fan of typedefs for blocks, but you’ll see them used often and you should recognize easily that defining them is Cuddle The Name:

typedef BOOL (^IsItSafeType)(NSInteger);

With it defined, assigning to it is what pattern? RIGHT! It’s Flip No Cuddle because you assign an anonymous value to the variable!

IsItSafeType alwaysSafe = ^BOOL(NSInteger x) { return YES; };

OK, Let’s Summarize!

Alright, so we have our two basic forms:

  • NSInteger (^myBlockName)(CGFloat param1) <-- Cuddle The Name for named blocks
  • ^NSInteger(CGFloat param1) <-- Flip No Cuddle for anonymous blocks

The one exception is with Cuddle The Name for method parameters where we cuddle the whole thing and pull the parameter name outside:

  • ((NSInteger (^)(CGFloat param1))outsideName <-- Cuddle The Name wants to be like other parameters!

But as you can see, since it’s a named block, using Cuddle The Name is perfectly consistent. Then, defining typedefs, we still have a named block and so we use Cuddle The Name there, too! And assigning to the typedef? Yep. Flip No Cuddle.

Simple! Hopefully, this helps us memorize this very strange syntax. :-)

  • Print
  • Facebook
  • Twitter
permalink

, ,

Previous Posts