We've (Koa + me = MokaSocial, LLC) finally pushed out Flicka.mobi the official portal to Flicka, our Flickr application for the Android platform! It will bring all the free functionality of the Flickr website and add tons of integration into the mobile platform. We're hoping to be able to launch the actual application by the beginning of Q2 this year. We'll see.
The page kind of tells you about the release and stuff but here are all the links:
It's been one frantic push to get the code base stabilized and things to a place where we can finally start talking about it. There isn't much about the Google Android SDK on the web so that's probably the biggest challenge. Also, the Java library we're using for our interactions doesn't seem to have everything.
Anyway, it's been a wonderful dive into Java and I've been thoroughly enjoying it. We're hoping it's a successful mobile platform application; one in a series of many increasingly complex and sexy!
Special thanks to those that have been helping. The organization, insight, and comradeship has been awesome!
Okay so I just have to share some awesomeness.
Dragon Age: Origins is one of the best role playing games I've played in a long time. The twists, pace; it all is so very interesting. It's kept me on the edge of my seat and I've actually sat there jaw dropped enjoying the emotions and story unfold.
Uncharted 2 is another fantastic cinematic story telling adventure that I love as much or even more than the original. It has a lot of the same creative story writing the previous title I mentioned above but it sets in the current time and world. I love the humor.
Finally and definitely not the least, DJ Hero is effing amazing. Take out the guitars and enter a turntable styled controller. I was a little skeptical at first but after playing a few rounds it's turned out to be an awesome journey into musical nostalgia and sexy rhythms.
With every one of these titles I am barely into them and hope there will be sequels. I felt like we're actually back to a time when there is some good story telling and exciting things to experience in game.
Recently I tried to get my Android Virtual Device (AVD) to run on my recently updated Ubuntu install and ran into the usual disheartening array of messages, errors, and other strange cruft that comes with that. Start and finish buttons in the Eclipse IDE weren't responding. I tried running an AVD and got messages like "could not find virtual device".
There is a decent page on fixing the AVD problem in Windows and although anyone with half a wit can extrapolate and figure out that the similar can be done to fix the issue in Linux, I've done that and share:
ln -s /root/.android/avd ~/.android/avd
To summarize (for both cases), we're creating symbolic links from where the Android SDK thinks the AVDs should be to where they actually are. You will probably need to delete the directory 'avd' within your ~/.android directory before running that command.
While I'm at it, there is some general wonkiness getting Eclipse 3.5 to run properly on Ubuntu 9.10. I was having trouble with groups and owners (Android SDK installation has them set to root when you install so you'll have to chown and chgrp recursively through the tree) and sometimes certain features simply don't respond. The following code seems to alleviate the IDE issues.
Code:
#/usr/bin/bash | |
export GDK_NATIVE_WINDOWS=1 | |
`~/bin/eclipsePackage/eclipse3.5/eclipse -vmargs -Xms128M -Xmx512M -XX:PermSize=128M -XX:MaxPermSize=512M &> /dev/null` & |
This assumes that you are running Eclipse on Linux via a Bash script. Most of the command is from the usual Ubuntu/Eclipse forums on how to start eclipse. The important line is the one about the GDK stuff.
I hope that helps. We've been running Android 1.5, 1.6, and 2.0. Each time a new version gets released we all need to tweak things here and there. With how young the SDK is and how little there is about it out there the more stuff we can all share the better.
I've been switching off game mode and back into creative music recording mode with the completion of my most recent game Borderlands. I agree with Play magazine's assessment. It's a cross between Half-Life 2 and Fallout 3 taking on the cartoon approach and injecting a good amount of humor. I liked the game all the way through except the ending which I felt was massively under explained and felt rushed through. "You won. You may quit when ready." comes to mind.
I also bought an additional Wii-mote and the New Super Mario Brothers game. It is a fantastic ride into memory lane. Again, the Play magazine review nailed it. It doesn't add anything leaps and bounds new and multi-player gets to be crazy at higher levels... but... I question the writers of that mag's game n00bness. Part of the fun in multi-player is how ridiculous and fun it is to try and get 4 people to go in the same direction without killing one another. It's been fun to play with the kids and it's brought the whole family together and for that the $50 or so was worth it.
Finally, I got my hands on Left 4 Dead 2 and to put it simply: awesome. They successfully taken what made the first game a hit and expanded it. More weapons to choose from, more interesting scenarios, and great sound. They bring back all the original monsters (although the "tank" still reigns supreme) and add some new twists. The difficulty in some areas seems a little off but I am happy to get a challenge. It seems the trend lately has been to make games enjoyable over challenging.
I am looking forward to getting my hands on Dragon Age: Origins, Call of Duty: Modern Warfare 2, Bayonetta, The Saboteur, Uncharted 2: Among Thieves, Final Fantasy XIII, Forza 3, Valkyria Chronicles, Gran Tourismo 5, Dante's Inferno, DiRT 2, Wet, Diablo III, MagnaCarta 2, Resident Evil 5; just to name a few. Doesn't help that my Xbox 360 has officially died. I guess I'm not too sad. I needed an excuse to get an Elite. But still, $300. Sad panda.
I'd like to play this a bit but as I poise to post about Crystal and my collaboration, I know I am running low on time.
While carousing the code base I've been alerted of the existence of an interesting function:
PHP:
public static function the_answer_to_life_the_universe_and_everything() { | |
| |
$calculation = sqrt(9) * 12; | |
$calculation = pow($calculation, 2); | |
$calculation = ($calculation / 4); | |
$calculation = ($calculation - 4); | |
$calculation = ($calculation / 10); | |
$calculation = ($calculation + 10); | |
| |
return $calculation; | |
} |
Brilliant. +2 Intelligence, +4 Charisma if you get the reference. Yes, this made my day and yes, it was worthy of a blog post.
Recently I was having a discussion about putting together an API and some ideas about caching, rate limiting or flood protection, design patterns for rendering the output, scalability, and security came up.
A while ago I came up with a rate limiting class. It wasn't as thoroughly tested as I would hope as I left a little over a week after putting this together there, but basically we use time as a cross thread limiter for all connections. If we wanted to limit a particular user, then we'd simply have to create a unique key for the memcache entry for each user.
This logic uses time (as Unix timestamps with microseconds) as a method to "charge" each request against the server a "fee" which accrues against the max or limit. As time moves forward, it removes accrued cost from the memcache saved value.
The beauty of doing rate limiting in code is it allows the developer to manage flow and how limits are handled to protect our databases and CPU load; dishing out less expensive and properly (and expected) formed API responses.
Here's the code:
PHP:
//////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////// | |
// RATE LIMITER CLASS - rateLimiter.class.php | |
// | |
// @date: 2009.05.21 | |
// @author Michael Hradek <mhradek@gmail.com> | |
// @version 1.0.0 | |
// @license Apache License, Version 2.0 | |
// | |
//////////////////////////////////////////////////////////////////////////// | |
//////////////////////////////////////////////////////////////////////////// | |
| |
//////////////////////////////////////////////////////////////////////////// | |
// INCLUDES | |
//////////////////////////////////////////////////////////////////////////// | |
| |
require_once("initializeMemcache.class.php"); | |
| |
//////////////////////////////////////////////////////////////////////////// | |
// PRIMARY CLASS | |
//////////////////////////////////////////////////////////////////////////// | |
| |
class rateLimiter extends initializeMemcache | |
{ | |
private $rateLimitKey; | |
private $rateLimitMax; | |
private $rateLimitCost; | |
| |
private $memcache; | |
| |
function __construct($rateLimitMax, $rateLimitCost, | |
$rateLimitKey = "rate_limiter_key") | |
{ | |
$this->rateLimitMax = (float)$rateLimitMax; | |
$this->rateLimitCost = (float)$rateLimitCost; | |
$this->rateLimitKey = $rateLimitKey; | |
| |
$this->memcache = $this->initMemcache(); | |
} | |
| |
public function enforceRateLimit() | |
{ | |
$rateLimitDataMs = $this->memcache->get($this->rateLimitKey); | |
$currentTimeMs = microtime(TRUE); | |
if($rateLimitDataMs === FALSE) | |
{ | |
$this->memcache->set($this->rateLimitKey, $currentTimeMs, | |
MEMCACHE_COMPRESSED); | |
return TRUE; | |
} | |
| |
$timeDiffMs = $rateLimitDataMs - $currentTimeMs; | |
if($timeDiffMs < 0) { | |
$rateLimitDataMs = $currentTimeMs; | |
} | |
| |
$rateLimitDataMs += $this->rateLimitCost; | |
if($timeDiffMs < $this->rateLimitMax) | |
{ | |
if(!$this->memcache->replace($this->rateLimitKey, | |
$rateLimitDataMs, MEMCACHE_COMPRESSED)) { | |
$this->memcache->set($this->rateLimitKey, $rateLimitDataMs, | |
MEMCACHE_COMPRESSED); | |
} | |
| |
return TRUE; | |
} | |
| |
$rateLimitDataMs += ($this->rateLimitCost*2); | |
if(!$this->memcache->replace($this->rateLimitKey, $rateLimitDataMs, | |
MEMCACHE_COMPRESSED)) { | |
$this->memcache->set($this->rateLimitKey, $rateLimitDataMs, | |
MEMCACHE_COMPRESSED); | |
} | |
| |
error_log(get_class().": Rate limit enforced."); | |
return FALSE; | |
} | |
} |
The memcache class is simply something that reads memcache server configuration arrays and loads them into a memcache handle and returns it. I think with some larger volumes we can excuse things like misses in key lookups. We're already using a hashed configuration. Why add the trouble of retrying?
This morning I awoke and for the first time in my life made coffee. I hopped into the shower, dressed, and walked into a kitchen filled with the aroma of our newly acquired bean addiction. I poured it into my cup, dropped in a spoon of chocolate syrup, and touched a few drops of milk to it. Excellent. My newly acquired container, although a little pricey, has been working out well in keeping the grounds fresh.
I have also installed a keyboard tray on my desk to help organize it a little. I am pleased with the way it worked out but I admit that the additional distance I now sit because of the sliding tray makes my 22" monitor seem a little small. My goal has been to make my desk inviting and easy to work on music but I've rarely the time or energy to get inspirational. Ach so.
With my recent phone number change I've changed phones from my old Blackberry Flip 8820 to the MyTouch 3G. It's a fantastic device as far as mobile phones go. I am excited to start developing apps for it. The Android platform is available for a lot of different mobile devices and will surely be a wonderful learning experience into the world of Java programming.
I've gotten Eclipse and the Android SDK loaded. Now it's time get something done. I'll share what we've got going on soon. I'm just glad I didn't join the droves of Apple fanboys. Supporting Google, however, doesn't make me feel all that much better.
Recently I've been working on testing some code that throws exceptions. What a pain to test! I thought initially that I had just designed myself into disaster with my new objects. Functions should return results or boolean, right?
I am sipping on a mocha right now which I paid $3.65. It's so expensive I won't be doing it often but it's a nice treat. I used to get hot chocolates because I hate the taste of coffee but recently I hate some of that Kirkland Signature stuff at Nate's and it's bearable. A mocha is like a hot chocolate with the benefits of coffee with half the nasty taste of regular coffee. I am not sure why I hate the taste of coffee so much but here's to getting over that.
*sip*
I have been playing a couple games recently. The first is Hearts of Iron III. This game, now that patch 1.2 is out, is quite simply awesome. I have been playing as the Italians on my commute home from work and have really enjoyed because able to replay history during World War II as a nation which I traditionally do not play. I admit I have it set to easy right now but we'll see how it goes. My conquest of Yugoslavia has just begun!