Dawson City in Pictures

Dawson City, YT at the quiet pre-tourist time is a largely empty, sleepy town. The people are friendly, and the pace of life is slow. There are no traffic signals, concrete pavements or chain-owned shops to break up the atmosphere of this century old mining town.

I chose to make most of these photos black and white because it suits the character of the place.

Severe subsidence due to melting permafrost is evident in parts of town.
Severe subsidence due to melting permafrost is evident in parts of town.

DSC_0003 DSC_0010_2

With the snow melting, water pumps are running all day to drain the bides of water that collect around the town.
With the snow melting, water pumps are running all day to drain the bodies of water that collect around the town.

DSC_0027

The clock on Front Street from the riverside.
The clock on Front Street from the riverside.
The prominent CIBC building has been left to deteriorate for years due to an ownership dispute. It's now been settled, and restoration is underway.
The prominent CIBC building has been left to deteriorate for years due to an ownership dispute. It’s now been settled, and restoration is underway.

DSC_0040

The SS Keno originally transported metal ore for processing. It's now a historic site, much like the SS Klondike, and was the last sternwheeler to navigate the Yukon (Whitehorse to Dawson) under its own power in 1960.
The SS Keno originally transported metal ore for processing. It’s now a historic site, much like the SS Klondike, and was the last sternwheeler to navigate the Yukon (Whitehorse to Dawson) under its own power in 1960.

DSC_0052

A signalling light on the SS Keno.
A signalling light on the SS Keno.
The Klondike and Yukon converge just south of Dawson; ice on the former has already cleared, but the Yukon remains icy. Meltwater is collecting on the surface, but that doesn't stop locals from crossing it on foot.
The Klondike and Yukon converge just south of Dawson; ice on the former has already cleared, but the Yukon remains icy. Meltwater is collecting on the surface, but that doesn’t stop locals from crossing it on foot.
You can place a bet on the day and hour that the "Yukon breakup" of ice will occur every year, in a form of winner-takes-all lottery. Until that happens, there's no ferry so crossing on foot is the only option.
You can place a bet on the day and hour that the “Yukon breakup” of ice will occur every year, in a form of winner-takes-all lottery. Until that happens, there’s no ferry so crossing on foot is the only option.
The restored SS Keno is maintained on the dry dock beside the Yukon river as a tourist attraction.
The restored SS Keno is maintained on the dry dock beside the Yukon river as a tourist attraction.
The ice is thinning, with the river flowing fastest beneath the darker portions of ice.
The ice is thinning, with the river flowing fastest beneath the darker portions of ice.
This rope is attached to the yellow tripod on the ice, and is part of the annual "Break Up" event. When the tripod moves, ice on the Yukon River at Dawson has officially broken up.
This rope is attached to a yellow tripod on the ice, and is part of the annual “Break Up” event. When the tripod moves, ice on the Yukon River at Dawson has officially broken up.
Front Street from the CIBC building, with Moosehide slide up on the hill in the background.
Front Street from the CIBC building, with Moosehide slide up on the hill in the background.

12 Long-Distance Bus Travel Tips (for car people)

I’ve been on a bus more often this past month or so than I have for the past decade. Whilst naturally traumatic for the petrol head, I’ve collected together some tips of how to make use of shared automotive transport less terrible.

(The photo below was taken from a bus, because who wants to see a picture of one?!)

 

  • There are other people on a bus, you have not been hijacked. This is normal on public transport; and takes some getting used to.

 

 

  • Hydrate. Constantly. You don’t want to get to your destination and feel like a sloth on a lazy day. If you need to problem solve on arrival, you can’t let your brain become a raisin en route. This applies especially to those who aren’t morning people, and always arrive at the bus last minute in a pool of sweat.

 

 

  • Remember what your mother told you at the services: “Go now, even if you think that you don’t need to.”. You always need to (if you followed the last step properly), you’ll be glad you did when the loo is broken on the bus…

 

View from the service stop in Woss, BC.
View from the service stop in Woss, BC.

 

  • Take healthy snacks. This seems like a given, but being so used to just traveling with a credit card (and claiming back expenses where possible), I only realised how expensive service stop food is when I was on a budget. They’re also infrequent, which leads to unhealthy choices; if you’re starving at a 15 minute rest stop, you’re getting the first take-away you see.

 

 

  • Take a coat or fleece onboard. “But it’s air conditioned!” I hear you cry. It’s not for that; when you want to nap (and on an 8hr+ journey, you will nap) the rapid percussion of skull on plate glass is a recipe for a nice cranial bruise. Your coat is your cushion. In addition, at layovers on the Greyhound you have to be off the bus, and sometimes the waiting areas at remote terminals aren’t that cozy. That and in Canada, you might be boarding in sunshine, and alighting in snow.

 

 

  • Sit glass-side. For the napping. Some buses don’t have armrests on both sides, so if you nap aisle-side, you’ll wake up as you fall out of your seat on a tight bend. I’m not saying this has ever happened to me…

 

 

  • Research your route, if you like a view. This is straying into the “planning not traveling” domain a little, but if you’ve got a few spare minutes at the bus depot, use it to check for potential prettiness on the way, then sit on the side of the bus that will get the best views.

 

 

  • Sit mid-glass. This is for two reasons: you’ll get a better view of what ever is out there to the side, and you’ll have somewhere to rest your head that doesn’t have a sharp edge on it, as the pillars often do.

 

 

  • Get over your fear of bus toilets. If there is one and it’s working, use it. I’ve sat with people that have refrained form conversation for hours waiting for a rest stop, trying to focus their mind through the internal damage happening to them. I find this hilarious, as fortunately I can go anywhere (#TMI..). If you are sat next to one of those people, try to make them laugh.

 

 

  • [Bonus tip] If you’re prone to travel sickness, sit on the rear axle. Whilst this will be noisier as you’re nearer the engine, you won’t get flung around as much on twisty mountain roads as you’re at the pivot when the bus steers. You also get a wider field of vision out of the front and sides peripherally as you look toward the front of the bus, which I’ve also heard helps. (This one’s a bonus as I can’t confirm; I don’t do travel sickness.)

 

 

  • [Canada-specific tip] Pre-connect your phone/tablet to fast food restaurants and cafés. If you’re on a mainland route, you might have WiFi and and a power socket. Cool! You’re sorted! If not, look out for A&W burger restaurants, Starbucks, Tim Horton’s and to a lesser extent, KFC whenever the bus stops – Greyhound depots tend to be near retail parks that have these. Some depots have free WiFi too, so that’s another option. They usually have free WiFi that spills out into the surrounding area, so if your phone already recognises the names of the hotspots you can save precious seconds syncing before the bus drives out of range again.

 

 

  • [Blogging-specific tip] Use the right mobile apps to remain productive whilst you’re offline. I use Pocket to buffer articles to read later (stripped out articles sync automatically for offline reading), Falcon Pro and Evernote for writing things like this blog post when there’s no signal. Instagram let’s you take photos whilst you’re offline, so if you see something cool, take a photo and just hit the spinny refresh thing later on when you’re back on the grid. If you’re a traveling smartphone addict, be sure to check out the post on my essential travel apps.

 

Photographing the Aurora Borealis

I’ve not posted for a while (been having too much fun to stop and type!), but wanted to share my findings of my first attempt at trying to photograph the Northern Lights from Whitehorse last night, and show off some of the more successful images. It was the first time I’ve ever seen the aurora, so I was keen to capture something to remember the night.

A time-lapse image that I created with G+ autoawesome.
A time-lapse image that I created with G+ autoawesome.

Preparation

Clothes

I thought that I was going to be freezing cold, so layered up with my running gear as a base layer; lugging a bag full of camera equipment up a hill, I expected to get a bit sweaty so didn’t want a soggy cotton base layer reducing my cold endurance.

I then had a cotton t-shirt, jumper, hoodie, fleece and a breathable but windproof Rab rain jacket on top – having done some night walking, it’s all about reducing potential sweat chill whilst keeping air tight. I wore running gloves as they are warm but very thin, which makes using the buttons on the camera possible without having to de-glove at any point. Thick walking socks and winter walking boots kept my feet away from the icy ground.

That combination kept me comfortable for the ~2-hours that we were out, despite the temperature being a solid single figure negative the entire time. I wasn’t even cold when we headed back (but the others had had enough!).

Camera Kit

I used my Nikon D5200 with a Nikon AF-S NIKKOR 50mm f/1.4G Lens. Whilst the focal length is longer than ideal for this type of photography, I’m only carrying that and a Nikon AF-S DX NIKKOR 55-300mm f/4.5-5.6G ED VR Lens, which whilst being an excellent, versatile lens, wasn’t as fast as I thought I’d need for night shooting, and the 50mm has a marginally wider angle.

I mounted it on my Manfrotto 732CY tripod (no link as it doesn’t seem to be on Amazon any more…), which I have fitted with a Manfrotto MH293A3-RC1 293 Aluminium 3 Way Head with RC1 Quick Release. I’m glad that I opted for a lighter model, as it’s been everywhere with me in my rucksack since I left the UK.

Everything was in or strapped to my trusty Incase Photo DSLR Sling Pack Black, which has survived well so far during my travels despite being a bit of a trendy city bag rather than a rugged kit lugger.

The last crucial piece of the gadget puzzle is the Timer Remote Control/cable release, which is useful if you want to take shots without camera shake and don’t want to configure the shutter delay in-camera every time, or hold the shutter open to experiment with exposure times. This model also has an LCD display and programmable shutter timer, which makes time lapses easy; you set up the interval and duration of shutter openings, press the Start/Stop button and let it do its thing.

Disclosure: All of the above product links are via my Amazon UK referral links, so if you click through and buy something I get money from the referral to further my travels and gadget purchases. 🙂

Lastly, don’t forget to fully charge, and take spare batteries if you’re going to be out there for a while. The best time to shoot the lights is on cold, clear nights, and the cold does affect the performance of batteries. You won’t get as long out of them as you would in milder conditions, and some recommend putting your batteries in your pocket until you need them when it gets really cold.

Camera Settings

First off, remove your lens filters; you’ll get some annoying moiré on long exposures if you don’t for reasons I won’t go into here (if you’re interested look, up diffraction interference patterns).

After some playing around in full Manual mode, I used the following settings for most of the best shots:

ISO: 1000 – 3200

Aperture: wide-open at F1.4

Shutter Speed: 3″ – 6″
(only possible with fast lenses, I’ve heard that 30″+ can work for slower lenses but you’ll get star trails and the aurora won’t be as crisp over about 15″)

Enough of this, where are the pics?!

Here are a few of the best. Back indoors I can see that some are pretty noisy due to the high ISO, and it got worse throughout the night as the camera warmed up. I’m pretty pleased with the results for a first try though, let me know what you think in the comments.

48hrs in Kelowna

I had high hopes on the way into the Okanagan Valley, having taken the Greyhound from Pacific Central in Vancouver there were some great views on the way up, so couple that with the fact that if you put Kelowna into Google Images you see nothing but beautiful shots of a lake and the beaches that surround it, I was sure that I was onto a good thing. My mistake was assuming that the town was sunkissed all year round; all of the photos were taken in the summer, obviously.

Treelined beach is just next to City Park.
Treelined beach is just next to City Park.

Slight gloom aside, Kelowna is a nice little town. Okanagan Lake that separates the east and west portions of the town is a pleasant, scenic stroll.

A beach on the East side of Lake Okanagan.
A beach on the East side of Lake Okanagan.

I headed to the town centre, to get a local perspective, and was greeted by a local chap with a shopping trolley full of what I assume to be his life.

“You’re not gonna get hit eh?”

“I’m sorry?”

I cautiously responded.

“Your fluorescents, no driver’s gonna miss those on the crosswalk!”

I was suddenly aware that I was dressed like a city muppet; my bright yellow-laced trainers (quite the thing in Van), and lack of trucker cap outlining me as “not from round ‘ere”.I jovially agreed.

“Safety first, right?”

“Best way for it. God bless ya!”

He carried on pushing his trolley, leaving me amused that such a conversation just happened, and that he wish me well! In England, I’d have expected just:

“Oi! Twat-trainers! **** off back to the city.”

So even if it’s just the tourist angle I’m getting, people are generally as nice in Canada as their reputation lead me to think before I arrived, and it’s pleasant. We could all do with more of that.


The town centre was in the midst of reconstruction work, with what looks like a pedestrianised area being constructed between the two main coffee shop-lined streets. I chatted to some of the locals, some students from the UBC campus up town, and a couple of bar regulars. All expressed the same view – “this place is dead out of season. Noted, and observed.

So it was a good opportunity to catch up on some reading, sleep and healthy eating (Ok, that last bit’s a lie, I went to Smoke’s one night…). The hostel was good, another of the Samesun chain that I stayed at in Vancouver, and there were some nice people there to chill with.

For future reference, visit Kelowna in the summer. It’s when all of that “awesomeness” that you hear so much about, happens. Alternatively, go in the winter if you’re into skiing; I’ve heard good things about Big White.

First Impressions: Vancouver

Having arrived here on Thursday, I thought I’d post a few topics that I have found to be notable from the past few days. These aren’t necessarily highlights, nor is it an exhaustive account, but instead some general first impressions of the place from someone who has never been here before. Here goes:

Stanley Park

prospectpoint

crow

It is safe to say that this place is no secret as every tourist brochure virtually screams about its loveliness, but that fact does nothing to dilute the beauty of this little oasis of nature nestled alongside the downtown part of the city. The first full day that I was in the city was spent wandering the seawall from Canada Place to the Lionsgate Bridge, where I cut in past Beaver Lake and walked uphill toward Prospect Point Café; a cozy spot with a great view and a log burning fire. I still find it surreal to have this type of setup in the midst of a city; you really couldn’t ask for much more if you’re after an outdoorsy lifestyle with the comforts and luxuries of modern life.

How are you today?

I am loathed to use stereotypical comments about nationalities in general (indeed the mere thought of it causes me pause and the need to obsessively adjust my monocle between sips of Earl Grey), but to not say that the Canadians are a broadly polite bunch would be to omit one of the most unmistakably pleasant aspects of the Vancouverite that I have witnessed so far. I had breakfast this morning with a new group; one German, one Czech and one Japanese, and we were unanimous in our recognition and admiration of the way that everyone in this city genuinely seems interested in how you are today. I am not talking about that forced, scripted fixed smile that you get in certain parts of the USA, but a sense of genuine interest. It is completely at odds with what I am used to in the UK, where eye contact is generally frowned upon, and people look at you at best quizzically when you say good morning, and at worst think you are about to mug them (though maybe that’s just my face…).

Homeless People

This is so noticeable that I would be neglectful to not mention it: there are homeless people everywhere in downtown Vancouver. Having discussed it with some people in the city, including one helpful homeless bloke called Patrick (who I mention below), it seems to be the climate that brings those without fixed abode to lie on the streets of this picturesque coastal city. It doesn’t take much figuring out, as at the time of writing Vancouver is one of only a handful of places in Canada where the temperature is currently above freezing, and the causes of them getting there in the first place are the usual combination of rising house prices and lack of unskilled job availability. Hopefully the plans that the city have for the area will improve that in coming years.

The weather across Canada on the morning of the 18th March 2014. Source: Government of Canada

Gastown

DSC_0171

If they don’t call this the Shoreditch of BC they should, albeit a cleaner less “tagged” version (it seems that Vancouverites aren’t big on graffiti). Bearded hipsters: check, ‘custom’ fixie bikes: check, ironically-named coffee bar called Coffeebar: check, MacBooks and chai lattés everywhere: double check. It doesn’t quite have the edginess that London’s version of a faux-rough neighbourhood has though, and as the oldest part of Vancouver has touristy relevance that I can only imagine irritates the digital natives that dwell there. The barista in Coffeebar wasn’t even able to maintain her fixed expression and deeply trendy nonchalance throughout the entirety of our commercial interation, delivering my drink and snack with a sudden smile. No, no, no, that’s all wrong. You just wouldn’t stand for that sort of politeness in Shoreditch. I didn’t dwell in the coffee shops there for long, and dodged through a flashmob practicing on the pavement outside (yes really, I hadn’t ever though that they did those, isn’t it cheating?), and headed east further into Gastown.

Note
After a few comments saying “dude, why do you hate Gastown?” I thought I should add: I don’t! In fact I really like it! To me it’s like a cleaner, nice version of a part of London that I also like! No hate, just a healthy dollop of sarcasm.

Except it wasn’t Gastown that I was looking at, it was Downtown Eastside.

DTES

I can’t claim to have been completely unaware of Vancouver downtown’s notorious rough district, but I wasn’t sure exactly where it was or whether it was as bad as the locals made it out to be. I headed south west, and met a homeless chap called Patrick walking the other way. We had a good chat, he immediately clocked my accent as English and guessed that everyone will assume that I am Australian (eerily accurate, as I’d been asked what part of Australia I was from in the FatBurger in the Harbour Centre earlier that day).

We had a good chat, he told me his mother was a war bride of a RCAF ground crewman based in Winchelsea, East Sussex; his patter was good, and the details were accurate enough to not just be bullshit, and it beats the usual begging with a cup approach, so I gave him a few dollars for some soup and socks at the nearby community centre. I am not naive enough to assume that is definitely where the money went, but the way I see it he earnt it by giving an Englishman some good Gastown tips (he pointed out a few English-owned pubs in the area that will give you a free pint if you show UK ID!), and his warning to definitely not to go the other side of Cambie Street, and if I was curious to see what it’s like, not to go alone. Ideally drive through it. I thanked him and walked on.

I went right through an alleyway between two trendy shops and was immediately faced with a scene so completely at odds with where I just was moments before. You literally go through a doorway at the end of an alley and go from trendy coffee shops to two people smoking crack whilst leaning on a shopping trolley, in broad bloody daylight! Prime location for some edgy street photography, but Patrick’s warning, my conspicuously bright orange Rab jacket and the fact that I was carrying some expensive kit meant that I didn’t think it was the best time to rock out the Nikon 55-300mm and poke it in some junkie faces. Mark one eyeball then was my camera.

I zigzagged southeast, past a few seriously sketchy looking “hotels”, lots of boarded up windows and a few people thinking that shirt buttons were optional whilst walking down East Cordova Street. It is definitely less plush than Gastown, but it wasn’t exactly on par with a scene from The Wire. Rough, it seems, is relative, and I got out alive without any bother. It just goes to show that you shouldn’t always take doom and gloom warnings at face value, and if I hadn’t gone I wouldn’t have seen how stark the change is when you cross the road back out of the district; it is as if there’s an invisible forcefield surrounding DTES, as the opposite side of the road is completely different at the boundary.

Granville Island

I discovered this place by accident after walking a loop of False Creek, and I am so glad that I did. It has an upmarket seaside vibe, with seafood restaurants and little boutiques. Crucially for me it has an outdoor shop, so I was able to buy some Nikwax for my walking boots – so far the only thing that I have found that I need and have forgotten, and if that really is all I omitted I consider myself lucky!

DSC_0244

DSC_0245

DSC_0254

Saving time by coding consistently

[Disclaimer: I wrote and published this on my phone whilst sat waiting in a café; if it reads a bit slapdash, it’s because it is! If you’re after a code rip, the snippets are in helpful little boxes. You’re welcome. :-P]

When working on projects that don’t have a set of “house rules” on logging, it is dangerously easy to be lazy.

I am also an advocate of making life easier for your future self; who hasn’t cursed “yesterday me when their groggy barely-conscious self is confronted with a tight morning schedule and a glowing fuel light? Amiright?

Um, ok… Well aside from arriving on time to appointments, creating good coding habits frees up brain bandwidth for creating cool new things, and produces the collateral benefit of reducing silly mistakes.

As a developer who specialises in object-oriented languages, I’ve been creating my own classes and libraries since I learnt how, back in my early Java days. In my opinion, objectifying code is an incredibly powerful productivity tool, and it worries me when I see beginner tutorials that don’t focus on this aspect; anyone can make a long class containing every function needed, and make it work, but in a production environment you’re doing it wrong! OO language compilers are optimised for object handling and memory clearing methods that favour small, granular components, not vast memory hog objects that are basically procedural.

Procedural is not the way that the world works. If you had a car that failed to start because the wing-mirror had broken off, it wouldn’t sell (in fact it wouldn’t even get through DFMEA analysis prior to a prototype build; I digress). Why then would you write a program that mixed UI functions (wing mirror) with network/data handling (ignition circuit)?!

In the same way that I like to use my favourite pencil when sketching (a Mitsubishi Kuru Toga propelling type, if you’re wondering), I have some little bits of code that I put into every Android app that I develop to make my life easier. It’s not quite boilerplate code, as it’s not part of a template, but a utility library that allows me to give my code consistency without bloat.

Consistent Logging

I know that a lot of people like to bring in external logging libraries to  their apps, indeed I’ve used Log4J a lot in larger pure Java projects, but a  lot of the popular frameworks don’t play nice with Android, and in some cases  (being designed for server-side/desktop applications) are detrimental to  responsiveness and battery life on a mobile device. So I prefer to use the  provided base classes and functions where possible. In fact, my logging function  is tiny.

When you’re logging in Android, you’d normally have something like this:

// This goes where you put your other class-scope declarations.
private static String LOG_TAG = "MyClassTag";

// This goes where you actually log stuff.
Log.i(LOG_TAG, "What I want to say.");

This leaves you wide open for laziness, as a helpful log entry like:

02-28 12:33:47.636: I/MyClassTag(988): Instantiating required variables for MyClass map component.

Rapidly deteriorates into:

02-28 12:33:47.636: I/MyClassTag(988): vars done

This is sloppy, but not technically a problem. However that sloppiness costs you time when you want to try something out quickly, or start to get tired and lose your eye for detail (~3am in my experience). Once you start  copying and pasting code around, you can end up with the wrong log tag appearing  in a class;  if you start to get two classes reporting identical tags, you’re in  for a really frustrating debugging session…

My solution, is this little function.

// This goes where you put your other class-scope declarations.
private String getLogTag(){
    this.mResources.getString(R.string.app_name);
    String log_tag_output = "";
    if (LOG_TAG!=null) log_tag_output = ":" + LOG_TAG;
    return this.mResources.getString(R.string.app_name) + log_tag_output;
}

// This goes where you actually log stuff.
Log.i(getLogTag(),"Stuff you want to say.");

Rather than being a dumb variable, ripe for a fat-fingering, the log tag becomes a mini report of which class it has been called from, and can show you at a glance if you’ve got an erroneous LOG_TAG declaration in a class where it shouldn’t be.

[Note] If you intend to keep logging enabled in a production version, you can reduce the memory cost of this function by assigning the “mResources.getString” response to a string variable in the class constructor. I switch logging lines off for production however, so am ok with the load incurred during the resource retrieval.

[Optional] In addition, I put the usual static string declaration in the class if I want to add  additional information to the tag – this works well if you have more than one  version of an identically-named class; if you’re detecting a tablet as opposed  to a phone form factor device for instance.

// Additional log tag info for this class.
private static String LOG_TAG = "NXD-version";

On its own, this doesn’t save me a lot of time. If I add up how much time I must have saved in aggregate from not having misleading logging errors in my LogCat trace, it comes in at days.

Repairing “org.eclipse.mylyn.tasks.ui” Eclipse start-up freeze on Mac OSX

Excuse the shameless “fishing for a search string” title, but it just took me over an hour to find a fix for this so, so I’m paying it forward.

The problem

This issue appears as you start Eclipse after an incomplete shutdown on a previous session – i.e. if it was force closed. If you search for this problem you’ll see a lot of sledgehammer fixes suggested:

“Delete your workspace and reimport your projects.”

“Delete your metadata directory and reimport.”

“Delete all of the hidden files in your workspace.”

etc.

The very worst recommends completely removing Eclipse and starting again. To be clear DO NOT DO ANY OF THESE! The solution is far too aggressive, and it loses your workspace configuration settings.

The problem occurs because Eclipse quits before it is able to delete a hidden “.lock” file in the workspace metadata. Upon restart it scans the metadata and sees this lock file, and as there is no pending task to clear it in the current instance, it awaits a deletion that will never happen.

The fix

Force quit Eclipse from the Dock if it’s still hanging; the damage is done, you can’t make it worse by closing it.

Open up Terminal, and navigate to the folder that contains your Eclipse workspace, then use this line to remove the hidden file lock.

sudo rm workspace/.metadata/.lock

Next, launch Eclipse with the clean and refresh arguments, so that the instance knows to regenerate any metadata that looks weird.

cd /Users/YOUR USER NAME/Development/eclipse/Eclipse.app/Contents/MacOS
./eclipse -clean -refresh

That’s it!

If you think that this might happen a lot (or if you’re just really into scripting for fun… What?) you can record the above actions as an automator script, and create a shortcut to it in your Eclipse folder so you can quickly repair the problem again in future.

The credit for finding this fix should go to sulai on StackOverflow.com, as I learnt about it from his comment on this thread, so do head over there and up-vote their answer if it helps you.

Downloading an entire file via the Storage Access Framework

I’ve been working on an app that works with image files that the user selects using the Storage Access Framework (SAF) that was introduced with the release of Android 4.4 (API level 19). Whilst the new selector UI provides the user with an easy way to access files stored on their device and in the cloud seamlessly, it doesn’t necessarily give developers the same ease of use.

It was straightforward to access the images and display them in an ImageView, but I found that it wasn’t the file that I was working with but a cached version of that file in memory. Whilst that’s great for memory management and responsiveness, I was after the Exif data that was stored within those files; that meant I needed to pull the file from its current location and reconstitute it on the device itself.

This part was lifted straight from the developer documentation. It’s provided here without comments in case you want to do a quick rip-n-run to try it out.

private static final int READ_REQUEST_CODE = 42;

public void performFileSearch() {

	Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
	intent.addCategory(Intent.CATEGORY_OPENABLE);
	intent.setType("image/*");

	startActivityForResult(intent, READ_REQUEST_CODE);
}

This is the juicy bit that writes the item that the user selects to a local file on the device.


/** We're overriding this function, which is called when an Activity result is
 * returned to this class. */
@Override
public void onActivityResult(int requestCode, int resultCode,
	Intent resultData) {

	/** 	This conditional statement ensures that we only run when the SAF has
	 *	returned us a result successfully (Activity.RESULT_OK) and that the
	 *	request code matches the one we used to request a file via the SAF
	 *	Activity (resultCode == READ_REQUEST_CODE). */
	if (requestCode == READ_REQUEST_CODE && resultCode == Activity.RESULT_OK) {

		Uri uri = null;		// Instantiate a Uri object to hold the image's Uri.

		/**	We need to make sure that the data returned isn't null, to prevent
		 *	any nasty null pointer exceptions. */
		 if (resultData != null) {

		 	try{
			 	/** Here we keep it all in a try-catch in case, so we don't
			 	 *	force-close if something doesn't go to plan.
			 	 *
			 	 *	This finds the location of the device's local storage (don't
			 	 *	assume that this will be /sdcard/!), and appends a hard-
			 	 *  coded string with a new subfolder, and gives the file that
			 	 *  we are going to create a name.
			 	 *
			 	 *  Note: You'll want to replace 'gdrive_image.jpg' with the
			 	 *  filename that you fetch from Drive if you want to preserve
			 	 *  the filename. That's out of the scope of this post. */
			 	String output_path = Environment.getExternalStorageDirectory()
			 							+ "/MyNewFolder/gdrive_image.jpg";

			 	// Create the file in the location that we just defined.
			 	File oFile = new File(output_path);

			 	/**	Create the file if it doesn't exist; be aware that if it
			 	 *	does, we'll be overwriting it further down. */
			 	if (!oFile.exists()) {
				 	/**	Note that this isn't just mkdirs; that would make our
				 	 *	file into a directory! The 'getParentFile()' bit ensures
				 	 *	that the tail end remains a File. */
			 		oFile.getParentFile().mkdirs();
			 		oFile.createNewFile();
			 	}

			 	/**	The 'getActivity()' bit assumes that this is being run from
			 	 *	within a Fragment, which it is of course. You wouldn't be
			 	 *	working outside of current Android good practice would
			 	 *	you?... */
			 	InputStream iStream = getActivity()
			 							.getContentResolver()
			 							.openInputStream(uri);

			 	/**	Create a byte array to hold the content that exists at the
			 	 *	Uri we're interested in; this preserves all of the data that
			 	 *	exists within the file, including any JPEG meta data. If
			 	 *	you punt this straight to a Bitmap object, you'll lose all
			 	 *	of that.
			 	 *
			 	 *	Note: This is reallt the main point of this entire post, as
			 	 *	you're getting ALL OF THE DATA from the source file, as
			 	 *	is. */
			 	byte[] inputData = getBytes(iStream);

			 	writeFile(inputData,output_path);

			} catch (Exception e){
				/** You'll have to forgive the lazy exception handling here...
				 * I'm keeping it clean for the sake of the post length! */
				e.printStackTrace();
			}
		 }

	}

}

/** This function puts everything in the provided InputStream into a byte array
 *	and returns it to the calling function. */
public byte[] getBytes(InputStream inputStream) throws IOException {

	ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream();
	int bufferSize = 1024;
	byte[] buffer = new byte[bufferSize];

	int len = 0;

	while ((len = inputStream.read(buffer)) != -1) {
		byteBuffer.write(buffer, 0, len);
	}

	return byteBuffer.toByteArray();
}

/**	This function rewrites the byte array to the provided filename.
 *
 *	Note: A String, NOT a file object, though you could easily tweak it to do
 *	that. */
public void writeFile(byte[] data, String fileName) throws IOException{
	FileOutputStream out = new FileOutputStream(fileName);
	out.write(data);
	out.close();
}

Here’s a screencast showing how it should look once you’ve got the example running.

The code is basic and outnumbered by the comments, so if you’ve worked with Android’s flavour of Java project before you shouldn’t have any problem understanding what’s going on. You can pull the full working example from the repo below; use it any way that you like.

Generating SVG with PHP

In one of my previous jobs, I had to develop a system that could automatically produce sheets of images that could be printed onto Avery type business card paper. The purpose was to create a ticketing system which could be used to distribute unique codes out to people so that they could log in with this unique key at a later date. It’s a fairly common use-case, and I’ve seen similar systems used at various conferences I’ve attended, in order to keep track of who’s accessing the free WiFi, or to track individual users to promo codes. In fact promo codes is probably the best analogy for it.

The process I used was to determine the layout of one of the tickets, then generate a PNG using the graphics libraries available in PHP to make a single image. I then rolled that image into a function call, with the promo code value and value of the promotion as arguments passed to that function via its constructor. Once I’d got that far, it was just a matter of looping through the database of promo codes, offsetting the images as required into a document model, then turning it into a PDF file for download or print. All of which sounds easy. However it wasn’t is straightforward as I’d expected it to be…

For one thing, these tickets needed to look right, so the graphic designer on the project supplied me with assets showing how the tickets needed to look, with the text sections omitted so that I could overlay the unique codes onto the image. So far so good. The difficulty came when I was scaling and lining up the text with the other components on the ticket. Because the PNG function only yielded a result when the code was valid and complete, debugging became tricky; whenever something went wrong in my code, I’d just get a generic PHP syntax error with a line number, but I couldn’t always see what was happening behind that error. Long story short(ish), I fixed it eventually and rewrote the class to give me a text log so I could see what dimensions I’d left out or fat-fingered, to make debugging easier in the future.

If I were to attempt that project again, I’d forget the PNG generation idea completely, and use Scaled Vector Graphics; the SVG format. SVGs are generated by the browser render engine, and exist as markup, in the same way as a HTML page. In fact, SVG is based on XML, which is in turn based on SGML, just like HTML – so they’re consistent. Consistency is great in my opinion, because it means I can work with the same text editing tools, and come up with the same sort of time-saving scripts that I’d used with HTML. Less to learn, what’s not to like?

<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
 <circle
 cx="100"
 cy="75"
 r="100"
 stroke="black"
 stroke-width="2"
 fill="red" />
 <circle
 cx="100"
 cy="80"
 r="40"
 stroke="black"
 stroke-width="2"
 fill="yellow" />
 <circle
 cx="300"
 cy="80"
 r="40"
 stroke="black"
 stroke-width="2"
 fill="yellow" />
</svg>

The killer feature in my opinion, is the ability to view all of this markup when you’re debugging. Rather than getting random server errors and having to chase down the log files for your server, you can see if the syntax is wrong by opening up the source tab in your browser! Far less hassle, and would’ve been a major headache saver in the past.

It’s also really easy to learn if you’ve got experience, check out an I’ve put together here showing how to draw some basic circles with PHP and SVG.