Google I/O 2013 Recommended Sessions




Additional list of talks that sound interesting, but haven't seen them myself, yet.

(WARING: some talks might be interesting, but the speakers are terrible, which makes it impossible to follow.)

Android Track

Chrome Track

Cloud Track

Others


iOS: Reversing a NSArray

You can reverse a NSArray by writing your own loop iterating from the end towards the beginning and using a second array to add the items in reverse order.

Or you can simply use - (NSEnumerator *)reverseObjectEnumerator  from the NSArray class.

NSArray *sortedArray = [....]
NSArray *reversedArray = [[sortedArray reverseObjectEnumerator] allObjects];

How to rescue Spain

  1. Stop complaining about the government* and banks**. Get your own ass up! Take responsibility for yourself and the world around you.
  2. Learn proper English. English is the world's collective language (at least for now). Doesn't matter if you like it or not. That's just the way it is. Adapt to it or fall behind.
  3. Learn something that actually matters and practice it.
* "Every nation gets the government it deserves."Joseph de Maistre
** The Truth About Dishonesty


Some starters:

When you're done with that, ping me. I might have a job for you.

iOS: Displaying "Back" on the back button instead of the title of the previous UIViewController

The back button typically shows the title of the previous UIViewController, unless it's empty. However, sometimes you don't want to show the title of the previous. Sometimes you have a title that just doesn't make sense to show on the back button.

The easy option is to simply set the back button title yourself to @"Back" with the caveat that it will always be English, no matter what the device's configured language is. The better solution is to temporarily remove the title in the previous UIViewController and re-set it when returning.
-(void)viewWillAppear:(BOOL)animated
{
 [super viewWillAppear:animated];
 self.title = @"My title";
}
-(void)viewWillDisappear:(BOOL)animated
{
 self.title = nil;
 [super viewWillDisappear:animated];
}
This way iOS will automatically set the title to "Back" or to the equivalent for whatever language is configured for the device.

iOS: Facebook SDK 3.0 (beta) - access user's information

The new Facebook SDK for iOS has a convenient way to access user information via the FBGraphUser protocol in a nice "dot-syntax" manner. However, because the FBGraphUser protocol doesn't have an email @property, we can't access all the information like we do with the name (see example below). Nevertheless, as with the previous SDK, the NSDictionary still contains the email kv-pair and other user information, which is not populated via the FBGraphUser protocol and we can access it like we would have done it with a normal NSDictionary (since it still is just a normal NSDictionary).
if (FBSession.activeSession.isOpen) {
    [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary *user, NSError *error) {
         if (!error) {
             self.nameLabel.text = user.name;
             self.emailLabel.text = [user objectForKey:@"email"];
         }
     }];
}
Also, don't forget to ask for the email permission when opening the FB session:
NSArray *permissions = [[NSArray alloc] initWithObjects:@"email", nil];
[FBSession sessionOpenWithPermissions:permissions completionHandler:
 ^(FBSession *session, FBSessionState state, NSError *error) {
     [self facebookSessionStateChanged:session state:state error:error];
 }];
Source: stackoverflow.com

Use Chrome as the default browser on iOS

Recently Google released their beloved Chrome browser for iOS, which supports advanced features like Chrome for your desktop computer. The most interesting among them are the smart suggestions while typing in the omnibox as well as synchronized bookmarks, history and passwords, where especially the latter is a pain to enter on mobile devices, when using long and cryptic passwords.

It all sounds pretty awesome, but there is one problem with that: the default browser for iOS is still Safari. And I guess Apple has no interest in changing that. Luckily Raphael Caixeta came up with a few lines of code, that app developers can add to their application, so that at least those will support opening links on Chrome for iOS where installed. If the user doesn't have Chrome installed, it will gracefully fall back to Safari.

As a developer you simply have to use the following snippet, whenever you want to open an URL with an external web browser:

NSString *url = @"mobilejazz.cat";

// Open with Google Chrome if possible
if ([[UIApplication sharedApplication] canOpenURL:[NSURL   URLWithString:@"googlechrome:"]]) {
     [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"googlechrome://%@", url]]];
} else {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:@"http://%@", url]]];
}


For jailbroken devices there is another option: Browser Chooser, developed by Ryan Petrich. You can get it by adding rpetri.ch/repo as a repo to Cydia (Manage > Sources > Edit > Add) and then simply search for Browser Chooser.

Pricing Psychology: 33% more vs 33% discount

The Economist has an interesting article about the psychology of discounting.

The main claim of the article is
"Shoppers prefer getting something extra free to getting something cheaper."

which they "explain" with
"Most people are useless at fractions."

For example people don't realize that a 50% increase in quantity is the same as a 33% discount in price.
50% increase in quantity = 150% = 1.5
33% discount = 67% = 0.67
1 / 1.5 = 0.67 and thus 1 / 0.67 = 1.5
For those who still don't get it, we can also look at it the other way around:
a 33% discount on something that is 150% results in 100%
150% * (1-0.33) = 100%
and a 50% increase on something that is 67% also results in 100%
67% * (1+0.50) = 100%

Therefore if you're offered either a 33% extra for free or a 33% discount you should definitely go for the discount, since we already learned above, the 33% discount gives you a 50% extra for free.

Another marketing trick people often fall for is double discounting. So if a product has been reduced by 20% and then later on by another 25% percent, most people think 20% + 25% = 45% discount, while the truth is, it's only a 40% discount.
100% * (1-0.20) * (1-0.25) = 60% which is obviously a 40% discount
Note: values have been rounded to make them easier readable. If you perform the calculations yourself and you want precise results, use fractions instead of percentages, e.g. 1/3 instead of 33%.

Everything You Need to know about Machine Learning in 30 Minutes or Less

A brief introduction to Machine Learning by Hilary Mason in her talk Machine Learning for Hackers at Bacon. Unfortunately the video has restrictive settings on vimeo, so I couldn't embedded it directly, but please follow the link.

If you're interested in learning more, you can get a full video lecture from Hilary at O'Reilly.

Also check out the Machine Learning class at Coursera.


Steve Jobs on Average vs Best Software Engineers

“I observed something fairly early on at Apple, which I didn’t know how to explain then, but have thought a lot about it since. Most things in life have a dynamic range in which average to best is at most 2:1. For example if you go to New York City and get an average taxi cab driver versus the best taxi cab driver, you’ll probably get to your destination with the best taxi driver 30% faster. And an automobile; What’s the difference between the average car and the best? Maybe 20% ?  The best CD player versus the average CD player? Maybe 20% ? So 2:1 is a big dynamic range for most things in life. Now, in software, and it used ot be the case in hardware, the difference between the average software developer and the best is 50:1; Maybe even 100:1. Very few things in life are like this, but what I was lucky enough to spend my life doing, which is software, is like this. So I’ve built a lot of my success on finding these truly gifted people, and not settling for ‘B’ and ‘C’ players, but really going for the ‘A’ players. And I found something… I found that when you get enough ‘A’ players together; when you go through the incredible work to find these ‘A’ players, they really like working with each other. Because most have never had the chance to do that before. And they dont work with ‘B’ and ‘C’ players, so its self policing. They only want to hire ‘A’ players. So you build these pockets of ‘A’ players and it just propagates.”
~ Steve Jobs in Steve Jobs - The Lost Interview

Source: benlakey.com

Great UX for list selection

I just noticed that Facebook provides you with a great experience, when selecting a bunch of friends to invite them to join an event or page. This is especially dragging if you have hundreds of friends, however, Facebook came up with a few tricks to make it a very painless process.


Visual Summary

First to notice is that Facebook doesn't just provide a simple list, where one row equals one item. Instead it puts 3 items in one row, making it much faster to scroll through the whole list. This might not be the best idea for a simple text based list. In Facebook's case, however, they add a thumbnail of the profile picture to each entry, which makes it very easy for the user's eye to scan the list, even if it has 3 columns. You know how most of your friends look like, and if in doubt or in case of a strange profile picture, you can still quickly double check with the name next to it.

Filtering

The second important feature to notice is the filter drop-down menu in the top left corner and the search box right next to it. With the filter you can easily display only the friends, which belong to a certain group or region, while with the search box the displayed entries will be restricted as you type to the entered character.

An additional nifty feature are the filter options Recent Interactions and Selected, where the first one gives you your most important friends (the ones you've interacted with recently), while the second one displays all the selected user, so that you can get a quick overview before hitting the Submit button, without having to scroll through hundreds of entries again.

Selection

And the best part of it is in my opinion the way you can select entries and how selected entries are displayed. Because of the checkbox the user will immediately notice, that this is a selectable item. However, you can not only click on the checkbox itself, but also the related image and text next to it. Which makes it way easier to hit the target, rather than aiming for a little checkbox.

Also, instead of just marking the checkbox as checked, Facebook highlights the whole item with a subtle blue frame and background. Which makes it way easier to differentiate the selected from the unselected items, without having the eye constantly jumping between checkbox, image and name.

Worth noticing is that Facebook grays out users that can't be selected anymore, typically because they've already been invited before or even already joined the event.

On being lazy

"I divide my officers into four groups. There are clever, diligent, stupid, and lazy officers. Usually two characteristics are combined. Some are clever and diligent -- their place is the General Staff. The next lot are stupid and lazy -- they make up 90 percent of every army and are suited to routine duties. Anyone who is both clever and lazy is qualified for the highest leadership duties, because he possesses the intellectual clarity and the composure necessary for difficult decisions. One must beware of anyone who is stupid and diligent -- he must not be entrusted with any responsibility because he will always cause only mischief."
~ Kurt von Hammerstein-Equord (German General)

Related: Lazy people innovate (HN discussion)

Google Web Fonts

I was bored this afternoon, so I started playing around with random design stuff and at some point I discovered Google Web Fonts, which is by the way a pretty awesome project. 

Of course I ended up spending hours browsing through various font collections and simply being mesmerized. But well, there are worse ways of wasting a Sunday night.

In case you are curious: this blog's title (GEEK!mind) is now rendered using Play, while the main text is displayed in Droid Sans

How to reload your .zshrc

Stupid me, after editing my .zshrc I always invoked a new shell to apply those changes. Now I found out, that you can use your shell's built-in source command to reload your zsh settings.
sk@supernova:~/ > source ~/.zshrc
or, even shorter:
sk@supernova:~/ > . ~/.zshrc

Java: Customizing enums

After reading this you might wonder why I would write about something obvious like that. And I agree. It is quite obvious. Once you know about it. However, first I didn't know and neither did the other Java programmers I've spoken to. So I thought it's worth writing up a quick blog post.

Probably all of you already know about enums and use them as type-safe flags or enumerations:
enum Cardsuit { CLUBS, DIAMONDS, SPADES, HEARTS };
That is pretty basic and probably everyone learned that in Java 101. What was new to me, though, is that you can customize the enum { } pretty much like a class.

So for example, one day I was working on a XML parser implementation, where depending on an attribute value of a XML element I had to make a decision. Since in XML everything is a String I wrote a quick method which compares an enum to a String. But I didn't know where to put it in my code. I figured the best place would be within the enum itself. Not really thinking that it would work, but still curious I tried the following:
I tried to compile it and voilĂ : it worked! No errors, no warnings.

In my actual XML parser I then would only have to do the following:
if ( Cardsuit.CLUBS.compareToString(xmlString) ) { .... }
Of course there would have been many other ways to do this, but this solution seems quite clean and elegant to me.

Android: Hide your application's media files from the Gallery App

If you have a media heavy application it is very likely that you store the image, sound or video data on the sd-card, since it gives you a lot more space than bundling everything with the application. Also, it enables you to dynamically add, remove or modify your media data.


However, the problem that comes with it is, that all your media is public now and can be read by other applications, e.g. the Gallery App, which scans the whole sd-card for image files. To prevent other applications from scanning and displaying your media files, you can simply add an empty file called .nomedia in the root folder of your media data.

From the official Android documentation:
Name of the file signaling the media scanner to ignore media in the containing directory and its subdirectories. Developers should use this to avoid application graphics showing up in the Gallery and likewise prevent application sounds and music from showing up in the Music app. 

Debugging Client-Server Communication

Especially in mobile development you most likely have some client-server communication going on, which is often the source of a lot of problems and long debugging sessions. To make the debugging easier it is helpful to see what each side sends or receives. There are two UNIX tools that can come in quite handy in such situations:
  • netcat - to listen to all TCP and UDP connections on a specific port
  • cURL - to send 'fake' requests to a server
Both a very powerful tools and you can do a lot of stuff with them (e.g. write your own web server with a shell script). However, in this post we will keep it simple and focus on debugging a HTTP (JSON) communication between a web server and a mobile client (iPhone, Android, but could be pretty much any kind of client).


Listening to incoming requests

We start a listening server with
nc -lk $ip $port 
  • -l: listen
  • -k: forces nc to stay listening for another connection after its current connection is completed.
  • $ip: the IP/interface you want to bind to. Use 0.0.0.0 to bind to all interfaces and IPs.
  • $port: the port you want to bind to. Doesn't really matter which one you use, as long as the client uses the same one to connect to.

In practice it might look like this:
sk@supernova:~/ > nc -lk 0.0.0.0 8080
POST /rpc HTTP/1.1
Accept: application/json
Content-type: application/json
Accept-Encoding: gzip
Host: 192.168.2.3
Content-Length: 152
Connection: Keep-Alive


{"id":3,"jsonrpc":"2.0","method":"sendTestMessage","params":{"clientVersion":"0.11.4-debug","user":"sk@geekmind.net","imei":"32420214181983746","message":"This is a test message :-)"}}
In green the HTTP header and in orange the actual content, in this case a JSON-RPC message. While the header is mostly irrelevant to us, it might in some cases contain useful information to detect the source of the problem. However, more interesting, and in most cases more prone to errors is our own "custom protocol" and its implementation. By evaluating the content section we can now easily compare if there is a difference between what we were expecting to receive and what the client was actually sending out.


Sending "fake" requests to a server

Sometimes the problem may not be in the client's implementation of our communication protocol, but on the server side. The complementary approach to the above example is to send "fake" requests to our server and look at the response we get.

With cURL it is as simply as that:
curl -v -i -X POST -d $data $uri
  • -v: verbose
  • -i: include HTTP headers in the output
  • -X: HTTP request type. Defaults to GET if none given
  • -d: data

Applied it might look like this:
sk@supernova:~/ > curl -v -i -X POST -d '{"id":1,"jsonrpc":"2.0","method":"sendTestMessage","params":{"clientVersion":"0.11.4-debug","user":"sk@geekmind.net","imei":"1111111111111111111"}}' http://android.geekmind.net/rpc
* About to connect() to android.geekmind.net port 80 (#0)
*   Trying 74.125.43.121... connected
* Connected to android.geekmind.net (74.125.43.121) port 80 (#0)
> POST /rpc HTTP/1.1
> User-Agent: curl/7.19.7 (universal-apple-darwin10.0) libcurl/7.19.7 OpenSSL/0.9.8l zlib/1.2.3
> Host: android.geekmind.net
> Accept: */*
> Content-Length: 157
> Content-Type: application/x-www-form-urlencoded
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Cache-Control: no-cache
Cache-Control: no-cache
< Expires: Fri, 01 Jan 1990 00:00:00 GMT
Expires: Fri, 01 Jan 1990 00:00:00 GMT
< Date: Fri, 08 Apr 2011 09:19:32 GMT
Date: Fri, 08 Apr 2011 09:19:32 GMT
< Server: Google Frontend
Server: Google Frontend
< Transfer-Encoding: chunked
Transfer-Encoding: chunked
<
* Connection #0 to host android.geekmind.net left intact
* Closing connection #0
{"jsonrpc": "2.0", "id": 1, "error": "1", "message": "ERROR: user and IMEI do not match!"}}  
In red the response we got from the server. In this case we used a real username with a wrong IMEI and tested if the server generates the right response. In our case the server correctly produced an error.

If you're interested in reading more about the actual implementation of client-server communication on mobile devices, check out my blog post Android: Simple HttpClient to send/receive JSON Objects. The code is available on GitHub.

If you want to directly monitor a real connection I suggest that you have a look at tools like Wireshark and tcpdump. Wireshark has a GUI and is fairly easy to understand. It also helps to have a server instance running on your local machine (development server), so you don't need to figure out how to tap into your phones WiFi connection.

Visual Life

A collection of promo videos of Inte's Visual Life contest. Interesting people and inspiring to watch.


Check them out, if you get a chance.

The Age of Fire - Futuristic Interfaces

Here is a really well-made video about futuristic interfaces in a completely interconnected home environment. It shows the beauty and usefulness that comes with it, but also points out the inherent problems of complete interconnectivity.


Interesting challenges for User Interface Engineers and Designers :-)