For those of you who know me (which would include most people reading this post) you’ll note that I am a huge proponent of TDD and proper project hygiene. I describe project hygiene as the things you do to ensure a successful project with easy maintenance. I have recently been working to prototype such a project in Android but have been hitting several roadblocks along the way. Hi, I’m Cliff. You’re here because you want a nicely structured project. I’m here because I can’t seem to get my project in the right shape, so I’m complaining.
I started a while ago with an example chat app I had written as a guide to using IntelliJ to write Android apps. I even put up a video tutorial on the subject. I recently had been working to reuse my example which had a hard dependency on the Robolectric project. Robolectric is a cool toy that lets you perform REAL unit tests on Android. There are those who may say, I do unit tests all the tim using Robotium, or the Android JUnit packages… but these are not unit tests as they involve either the emulator or a physical device. The tests I have written run successfully on my laptop and take a fraction of the time that typical Android tests take.
I had my environment working about 7-8 months ago but so much has changed since then. Today when I tried to recreate my magic I had trouble trying to “install” Robolectric on my new Mac. (All my work had been setup on my old Mac.) I originally tried running with the older 1.1 Robolectric jar but then had to tweak my IDE envirnment variables to point to ANDROID_HOME which is so much fun on Mountain Lion these days. (It’s practically impossible to get IntelliJ to see custom system environment variables and the launchctl trick doesn’t work for me.) So the nI eventually decided after forcing ANDROID_HOME and getting a path not found on “~/android-sdk-macosx/platforms/android-10″ since my new Mac doesn’t have the older SDKs to install a later version of Robolectric. My thinking was, “maybe they’ve ironed out the details and finally fixed it so you don’t need env variable settings and older SDKs…”
If you visit the Robolectric home page you’ll see all the installation instructions point to a Maven POM. that does you no good if you’re starting from an existing Android project because it either
a.) Forces you to refactor your project using Maven standards
b.) Forces you to reverse engineer the pom to find out where the actual Robolectric jar is.
Both of these options are terrible for existing Android work and since many people rarely get to work on green field this presents a tough dilemma.
I eventually found a way to work around the issue by whipping up an equivalent ivy.xml and throwing together a custom_rules.xml to use in my Android project but it still sux on the surface because of the extra overhead involved with declaring a single Maven dependency in an Android project.
Step 1: create a custom_rules.xml.
Step 2: declare an Ant “-pre-build” target that performs the ivy resolve task and writes the dependecy jar files to your project’s “./libs” folder.
Step 3: create a custom ivy.xml that declares your Maven dependencies.
Step 4: Cuss because you realize it’s not trivial to invoke your custom “-pre-build” target in isolation to test your new configuration.
Step 5: Create a custom “ivy-resolve” target which your new “pre-build” target should now depend on.
Step 6: Test your “ivy-resolve” in isolation to ensure it pulls the correct dependencies.
Step 7: Cuss because your IDE’s built-in version of Ant does not include the Ivy jar.
Step 8: Either find the Ivy jar hidden on your hard drive and dump it into your IDE’s antlib or find your custom ant build tools and point your IDE to that.
Step 9: Repeat step 6
step 10: Cuss because your project’s “libs” folder has now exploded with unnecessary transitive dependencies including everything from ant to maven-model.jar to wagon to xerces.jar
step 11: Try to run your tests and realize that the dependencies declared don’t line up with the examples from the web site.
step 12: construct a blog post expressing your frustrations with the current state of Android development.
In the end I’m wondering why, in the year 2013, we can’t do any better out of the box. Why is it still a chore to practice proper TDD on mobile platforms? (I’m glaring at the iOS community as well because I don’t think that camp is any closer to out of the box TDD.) I would love to just open my IDE, click on a unit test, perform some hotkey combo Cmd+shift+F10 or something, and watch either red or green bars stretch across the screen without considering silly stuff like my environment, grabbing older SDKs, researching dependency matrices and the like.
By the way, I found out how to pull external dependencies into an Android project following this blog post. Nice little trick!
You’re writing an Android app and you need to do something slightly more than trivial. Maybe you want your app to snap a picture, maybe you need to capture audio. Maybe you just need to track where the user is. At any rate, your app needs permission to do certain things. Hi, I’m Cliff. You’re here because you’ve asked permission from your user base to do a bunch of stuff. I’m here because I’m learning the ins and outs of Android permissions. Destiny has brought us together and I’m glad to meet you.
I was going to make another long winded post but it’s late and I have other things to do. I’ll just sign off with a link to a site that documents some Android permissions. Maybe you’ll find it useful. You’re welcome!
I haven’t posted anything in a month of Sundays. I never understood why people use dumb phrases like “a month of Sundays”. If there were only Sunday “days” in the month then it would be kind of short because you only get four of them… and that doesn’t seem like it makes much sense. I say that because people use that phrase to indicate long elapsed periods of time and a month of Sundays is only four days. People should just get over themselves and say I haven’t seen you in four days without all of the, “I need you to do the Maths and figure out what I’m talking about”. People are dumb. I digress.
I was beginning to tell you about this thing I’m doing with web views. I did it because I’ve been asked how to do it like two times. I got tired of pretending to know what I’m talking about so I prototyped it and I’m going to post my stuff here and just point to this page from now on. Plus, like I said earlier it’s been a month of Sundays (or four days if you don’t like Maths). So here goes. For those three of you who visit regularly I’m sorta back but not quite. Testing the waters a bit.
Let’s start with main layout saved in a file call main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout android:layout_width="fill_parent" android:layout_height="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <WebView android:layout_width="fill_parent" android:layout_height="250dp" android:id="@+id/myWebView" android:layout_gravity="center"/> <WebView android:layout_width="fill_parent" android:layout_height="250dp" android:id="@+id/secondWebView"/> </LinearLayout> </FrameLayout>
We have a linear layout set to vertical orientation. There are two nested WebViews defined, “myWebView” and “secondWebView”. Each will appear one above the other. Next we define a main activity.
Let’s see our first HTML file, view1.html:
I used to be so much better at gluing code to blog posts but these days I don’t even remember how to log in to my site as the administrator. With any luck, the code will be found as an attachment or maybe something with a little paper clip icon hanging on the side bar. I’m not really sure but I’ll figure that out now. There! I just remembered the Box widget on the right hand side. You can find my Jvascriptbridge.zip project there. Until next time… which might not take an entire month of Sundays if I get my act together…
Getting one’s act together is another one of those things people say. I’ve never acted nor do I belong to a drama club, so I would have a hard time getting my act together. For example, if I had an “act” how did it become disassembled in the first place? I would imagine various pieces of what would have been “my act” scattered randomly on the floor. I would probably hire somebody to piece it back together because I suck at act assembly. That would take a while because last time I looked in the Yellow Pages there was no section for “Act Assemblers”. I could find “Plumber”, and “Doctor” just fine. “Mechanic” was there, as well as “Actor” but not “Assembler”. It’s late, and I probably should go now. If you’re into programming stuff, check back. I promise I won’t ramble senselessly on my next post… unless you like my rambling. And if you do like it maybe I’ll put up one of those PayPal links so people can pay me for rambling. Yes it’s late. I should do other stuff like sleep. Thanks for reading! :)
You’ve been down this road before. You’ve added a parameter to a constructor and now you have 2 parameters with similar names. You merely want to distinguish between them both. A quick lookup to see how the original parameter is used reveals that it is not an “id” rather it is a shortcut. After refactor/rename action in your IDE you wait for satisfaction which should only take seconds. Several minutes tick away while a progress bar fills, refills and is eventually joined by several other progress bars each taking their time to fill to completion. Hi, I’m Cliff. You’re here because you’ve been staring at your screen patiently waiting for several progress bars to bring you refactoring pleasure. I’m here for much of the same reason.
Every so often I hit an area in my code that doesn’t refactor exactly as I had anticipated. It happens much less frequently since I’ve moved back into Java development and can use the world’s best refactoring IDE. Still it does happen from time to time. This morning I was bit when I attempted to rename a class member named “id”. Apparently the my IDE is having trouble tracking down all 5 usages in the current file as it scans my entire project for these 2 very common characters. I’m not sure why it’s happening (it’s still running as I type) but I am guessing it is because I inadvertently left the “scan all non-code usages” option checked. I’ve had much worse war stories of refactoring under XCode which I will save for the future but I felt compelled to share today’s horror story since it is so rare that I have such headaches these days. Refactoring is actually my favorite part of development as I incrementally massage horrific code into easily managble bite-sized chunks but every so often it pays to watch which options you leave checked in the refactor dialog.
You have a killer idea for an Android app. You’ve discussed it with the few folks who matter most, your buddy, your barber, and the clerk at the local convenience store where you buy your lotto tickets on Thursdays. They all agree you have a winner now all you need to do is create it! Hi, I’m Cliff. You’re here because you’re moments away from pushing the next $$multi-million app to the Android Market. I’m here to prepare you with the correct tools and know-how. Below is my 1st screencast, an introductory tutorial for using IntelliJ Idea. IntelliJ is what I consider to be the best IDE on the planet.
You left your Nexus 7 on all day and, unbeknownst to you, there isn’t enough power left in the device to draw the letter “A” much less boot the device. You plug it in and while noticing the familiar black screen, instinctively hold the lock screen button in an attempt to power it on. The Google logo followed multi-colored “X” which is eventually followed the home screen whets your appetite for some advanced Droid play only to hear an unexpected chime followed a power down notice followed by by static. Hi, I’m Cliff. You’re here because you’re locked out of your Nexus 7 and all of its robotic goodness. I’m here to comfort you, reassuring that everything is ok, there is always a way back in. Read below and you’ll be shaking hands with R2-D2 in no time.
I found the key to Nexus lockout on another forum and it totally restored my ability to power up in peace:
- Assuming your unit can boot long enough to do this, press and hold all the buttons (that is the lock button and both volume buttons) to give the device a hard reset.
- Keep holding the buttons till it reboots to the bootloader.
- Using the volume buttons, cycle through the menu selections and choose to power off the device. (The power off option will point to the lock button which you click to power it off)
- Unplug then re-plug the charger.
- You should now see the battery-charging icon. It shouldn’t boot up on its own anymore. Just let it sit and charge to full capacity.
You had a really slick idea. You wrote this TCP server that accepts socket connections and it runs on an Android device! You’ve been testing it all day and debugging it until it was bullet proof. You arrive home ready to test the last 4 liner modification you made just before leaving the office when you realize you left your device in the office! No worries, fire up the emulator and connect the test client on your mac to…? You test client expects an IP address and a port! Hi, I’m Cliff. You’re here because you left your Android phone on your desk underneath the 5oz bag of Lays BBQ chips. I’m here to give you some brief info on how to get your emulated Droid talking TCP to its host environment via a telnet session and a redirect command.
The first thing you need to do is determine which port your emulator is bound to. The port number is usually listed in the title bar of the Window your emulator runs in. (Unless you’ve specified an override, the 1st emulator instance you start will bind to port 5554, and the next will bind to 5555 and so forth.)
Next, open your terminal (or “cmd” command prompt on Windows) and start a telnet session on localhost. This will connect you the emulator control console where you can enter port redirect commands. The command for redirect is:
redir add <protocol>:<host-port>:<guest-port>
So let’s say your socket server is running on port 8080 on the emulator and you want to redirect all traffic going to port 8081 on your Mac (or Windows PC), you would enter:
redir add tcp:8081:808
You can now “exit” the telnet session and from thenceforth all traffic hitting localhost:8081 will be forwarded directly to the emulator on its port 8080! When you are done with port forwarding you can connect to the emulator control console again via telnet and remove the port forward with the following command:
redir del tcp:8081
These comands work equally well with UDP. Use:
redir add udp:9001:9000
To forward UDP traffic from 9001 on localhost to the emulator’s port 9000 and use:
redir del udp:9001
To undo the change when you are done. There are various other things you can do with the emulator console. For more info see the Android developer docs on Using the Emulator Console.
A short post for those who are wondering if I’m still alive. I got an error trying to run unit tests in an Android project under IntelliJ Idea and I got stumped. After a few minutes of Googling it dawned on me that I had chosen to run the test using a JUnit run configuration instead of an Android run configuration. That is when I right clicked the test method, my mind insisted on chosing the more familiar white window-looking icon with the red and green arrows instead of the Android icon, also with red and green arrows. I was associating the android icon with execute apk and not run tests. I now notice the little chevron-looking arrows and realize they refers to the red, green, refactor life cycle of development.. duh!