Categories
Tampa Bay

Tampa iOS Meetup, Wednesday, May 4th: Adding geolocation to our weather app

adding geolocation to our weather app

The next Tampa iOS Meetup has been announced for Wednesday, May 4th at 6:30 p.m.. This one builds on the previous meetup (but if you missed the last one, we’ll get you caught up) and is called Adding geolocation to our weather app.  It takes place at our usual spot: Energy Sense Finance, 3825 Henderson Boulevard (just west of Dale Mabry), Suite 300.

We’ll pick up from where our last meetup, Build a simple weather app (and learn basic network programming along the way), left off. The app required you to specify your location before it would report the weather. But that’s not how most weather apps work: they use geolocation to get your phone’s coordinates and provide them to the weather service. In this meetup, we’ll show you how to harness the power of iOS geolocation through the Core Location framework.

We’ll begin with a quick walkthrough of last meetup’s weather app, just as a reminder for those of you who were there, and as a way for those of you who weren’t to get caught up. Then we’ll get right into the business of adding geolocation capability to our weather app, so that when you run it, it displays the weather for your location.

At the end of this session, you’ll know how to make use of geolocation through Core Location. We’ll make the source code and presentation materials available at the end, to make it easier for you to start your own geolocation projects.

Join us this Wednesday, get to know your fellow Tampa Bay iOS developers, and get ready to learn and have some fun!

Tampa iOS Meetup is a monthly meetup run by local mobile developer/designer Angela Don and Yours Truly. While Tampa has a couple of great iOS developer meetups — Craig Clayton’s Suncoast iOS and Chris Woodard’s Tampa Bay Cocoaheads, we figured that there was room for a third iOS meetup in the Tampa Bay area, and especially one that would stray into other areas of mobile development. So we made one.

The Details

  • What: Tampa iOS’ Meetup’s “Adding geolocation to our weather app” session. Please sign up on our Meetup page so we can plan accordingly!
  • When: Wednesday, May 4, 2016, 6:30 p.m. – 9:00 p.m. We’ll have some snacks at 6:30, with the presentation beginning at 7:00.
  • Where: Energy Sense Finance, 3825 Henderson Boulevard (just west of Dale Mabry), Suite 300. See the map below.
  • What to bring: Yourself, but if you’d like to follow along, bring your Macbook and make sure it’s got the latest Xcode.
  • What to read in advance: If you’re one of those people who likes to do some readings ahead of a presentation, try this example location app written in Swift. We’ll be using our own tutorial material, but this may come in handy.
Categories
Uncategorized

Want to test an iPhone/iPad game?

Wine Crush is a simple “Candy Crush”-like game that I’m developing for my friends at Aspirations Winery in the nearby city of Clearwater. It’s the first of a few apps that I hope to publish to the App Store this year. If you’ve got an hour or so to spare and are the sort of person who always has ideas on how apps could be improved, this opportunity’s the one you’ve been waiting for!

Wine Crush is a pretty straightforward game. You play by creating matching groups of wine-related images — glasses of wine, bottles, corks, grapes and cheese — in groups of three or more. You can create horizontal matching groups…

Animation showing how players form a horizontal match in Wine Crush.

…or vertical matching groups:

Animation showing how players form a vertical match in Wine Crush.

You score points for creating matching groups, and the goal for each level of the game is to score a target number of points within a given number of moves. If you meet the goal, you get to proceed to the next level. If you don’t, it’s GAME OVER.

Anitra Pavka (3rd from left) and Joey deVilla (4th from right) at 'Wine-O Bingo' at Aspirations Winery, Clearwater, Florida.

“Wine-O Bingo” at Aspirations Winery, summer 2014. My wife Anitra’s third from the left, and I’m the smiling guy across the table from her, fourth from the right.

Wine Crush is designed as a promotional tool for Aspirations Winery, which is run by Bill and Robin Linville. My wife Anitra has been buying their wines for years. She took me to one of their regular “Wine-O Bingo” events in 2014 (pictured above), and made friends with them after entertaining their guests with a couple of their accordion numbers. Soon after, I approached them with a proposition: Would you like to have an iPhone game for your winery?

They said yes, and I got to work. Starting with the “How to make a game link Candy Crush” tutorials from RayWenderlich.com as a basis, I put together a game with wine-related imagery and Aspirations’ branding, using artwork that Robin provided. The backgrounds for the games’ levels are various labels for Aspirations’ wines, and there are a couple of buttons on the main screen that you can click to find out more about the winery.

For Aspirations, it’s a cute little way to get their name out their in a way that sets them apart from most other small family-owned wineries. As for me, this app is a way for me to help out some friends, sharpen my programming skills, build a portfolio, and gain some valuable experience with the App Store. Aside from a fair bit of free wine (for which I’m very grateful), I’m not getting paid for this project.

The title screen and two game screens from Wine Crush.

Wine Crush needs to be tested before I put it on the App Store. As the developer, I’m a little too close to the project to spot all the bugs and places where it could be improved. That’s where you come in. I’m looking for a small group of people who like trying out new apps to take a pre-release version of Wine Crush for a spin, point out problems and crashes, and give me some feedback. I will also ask you to test some other interesting iPhone/iPad/Apple TV projects I’m working on. It won’t be an all-consuming process; all I’m asking for is a little bit of your downtime and your opinions.

Does the opportunity to test and give feedback on soon-to-be-released iPhone/iPad/Apple TV apps sound interesting to you? If it does and you’d like to join the test group, drop me a line at joey@joeydevilla.com.

This article also appears in The Adventures of Accordion Guy in the 21st Century.

Categories
Uncategorized

Tonight at the Tampa Bay UX Meetup: Apple TV UX with Anitra Pavka!

apple tv fun facts

A slide from tonight’s presentation.

tampa bay user experienceI was scheduled to speak tonight at the Tampa Bay UX Meetup and talk about Apple TV UX with my wife Anitra, but as luck would have it, work commitments this evening with GSG’s biggest client have conspired to keep me away.

The show must go on, and it’s in very good hand. Anitra’s forgotten more about user experience than I will ever learn, what with her work as a user experience and web accessibility consultant. She also wrote the accessibility chapter in O’Reilly’s HTML5 Cookbook and was a technical editor for O’Reilly’s Universal Design for Web Applications book. She’ll apply her knowledge to the fourth-generation Apple TV user experience, and walk you through it. There’ll be a presentation, followed by live demos of Apple TV apps and interface. She’ll also point you to resources that you can use to help you design and even build tvOS apps.

It all happens tonight at 6:00 p.m. at the offices of 352 Inc., located at 5100 West Kennedy Boulevard, Suite 352 in Tampa. You can sign up and find out more on the Tampa Bay UX Meetup page. My thanks to organizer Krissy Scoufis for all her help!

Categories
Uncategorized

Developer news roundup: Android, iOS/Swift, and regrets and mistakes

Android

new android emulator

Click the screenshot to see it at full size.

Regrets and mistakes, part one

nuclear explosion

This question appeared on Server Fault on Sunday:

I run a small hosting provider with more or less 1535 customers and I use Ansible to automate some operations to be run on all servers. Last night I accidentally ran, on all servers, a Bash script with a rm -rf {foo}/{bar} with those variables undefined due to a bug in the code above this line.

All servers got deleted and the offsite backups too because the remote storage was mounted just before by the same script (that is a backup maintenance script).

How I can recover from a rm -rf / now in a timely manner?

Most of the answers were along the lines of: “If you’ve got backups, you’ll be fine. If you don’t, you’re about to go out of business.”

iOS and Swift

swift adjectives

Regrets and mistakes, part two

sad man at computer

From My Biggest Regret as a Programmer:

I could go on and on but the key is that you can’t make changes in how people do things in a technical sense unless you have the ability, the authority and the opportunity. Once you make that call and assuming you find the right places to grow, the sky is really the limit.

When I was on TV (Computer Chronicles) in early 1987 showing our product Trapeze the other presenter was Mike Slade who was product manager of Excel. At the time young me thought him some random marketing weenie (young people can be pretty stupid). Yet he started all these companies later including ESPN, worked for Apple in various leadership roles, was a good friend of Steve Jobs and started his own VC firm.

And today I am still just a programmer. Who’s the weenie now? I doubt I will ever be able to really retire. Thankfully I am still good at delivery (I was recruited into my present job by a former manager who needed what he knew I can do) but still all I will be until I croak is what I am now.

Categories
Swift Kick

How to build an iOS weather app in Swift, part 2: A little more explanation, and turning OpenWeatherMap’s JSON into a Swift dictionary

smartphone weather

Welcome to part two in a series of articles on building your own iOS weather app in Swift!

The previous article in this series showed you how to:

  • Get a key for OpenWeatherMap’s API for current weather data
  • Make a manual API call using your browser
  • Create a basic app to get the data from OpenWeatherMap
  • Tweak the app

In this article, we’ll explain the code that was presented in the previous article and make the next major step in writing our weather app: extracting the data from the JSON returned by OpenWeatherMap.

A deeper look at the code that gets the weather data

In the last installment, I gave you enough code to connect to OpenWeatherMap and retrieve the weather data, but never explained how it works. Let’s fix that oversight.

Our simple weather app makes use of the NSURLSession class along with some classes that go along with it. Together, classes in the NSURLSession family of classes give us an API for downloading and uploading data from the internet, in a number of different ways.

The diagram below shows the classes that our weather app works with, either directly or indirectly:

nsurlsession diagram

Here’s a slightly more in-depth explanation of the classes in the diagram above:

NSURLSession class Instances of NSURLSession are containers — collections of other objects — that provide an API for sending data to and receiving data from a given URL. You use the NSURLSession API to create one or more sessions, which are objects that coordinate one or more tasks, which are objects that actually transfer the data.
Shared session object The shared session object is a pre-made singleton instance of NSURLSession. It’s not as configurable as other NSURLSession instances that you can instantiate yourself, but for simple requests, such as the kind we’re making in our bare-bones weather app, it’s good enough. You access the shared session with NSURLSession‘s sharedSession class method.
NSURLSessionTask class As mentioned in the explanation of NSURLSession above, tasks are the objects within an NSURLSession instance that actually transfer the data. NSURLSessionTask is the base class for tasks.
NSURLSessionDataTask class

You typically don’t instantiate an NSURLSessionTask object, but one of its subclasses, and you do so by calling one of NSURLSession‘s task creation methods. NSURLSessionDataTask is the class for data tasks, which are used to download data from a given server into memory. We’re using an NSURLSessionDataTask instance to request and collect data from OpenWeatherMap.

In addition to data tasks, there are also upload tasks, which are used to upload data to a server, and download tasks, which are used for downloading data from a server into a file (as opposed to memory, which is where data tasks download their data to).

That’s the “big picture” view. Keep it in mind as we look at the code that does the downloading, contained in the getWeatherInfo function in the WeatherGetter class:

import Foundation

class WeatherGetter {
  
  private let openWeatherMapBaseURL = "http://api.openweathermap.org/data/2.5/weather"
  private let openWeatherMapAPIKey = "06db44f389d2172e9b1096cdce7b051c"
  
  func getWeatherInfo(city: String) {
    
    // *** 1 ***
    let session = NSURLSession.sharedSession()

    // *** 2 ***
    let weatherRequestURL = NSURL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
    
    // *** 3 ***
    let dataTask = session.dataTaskWithURL(weatherRequestURL) {
      (data: NSData?, response: NSURLResponse?, error: NSError?) in
      // *** 4 ***
      if let error = error {
        // Case 1: Error
        // We got some kind of error while trying to get data from the server.
        print("Error:\n\(error)")
      }
      // *** 5 ***
      else {
        // Case 2: Success
        // We got a response from the server!
        print("Raw data:\n\(data!)\n")
        let dataString = String(data: data!, encoding: NSUTF8StringEncoding)
        print("Human-readable data:\n\(dataString!)")
      }
    }

    // *** 6 ***
    dataTask.resume()
  }
  
}

I’ve added number comments to the code, which correspond to the explanations below:

  1. We use NSURLSession‘s class method sharedSession to get a reference to the shared session object, and assign that reference to the local variable session.
  2. We construct an URL using the URL for OpenWeatherMap’s current weather API, filling in the blanks with the name of the city that we want the weather for, and our OpenWeatherMap API key.
  3. We want to use a data task to request and retrieve the data from OpenWeatherMap. As mentioned earlier, tasks are created by using one of NSURLSession‘s task-creation methods. In this case, we’re using dataTaskWithURL, which we provide with 2 arguments:
    • The URL created in step 2, and
    • A completion handler that executes once the task is done requesting and retrieving the data. The completion handler will receive three arguments, which we can work with:
      1. data: If the request was successfully made and the data was successfully received, this will contain that received data.
      2. response: The response from the server.
      3. error: If the request was not made successfully or the data was not received successfully, this will contain information about the error.
  4. If the error argument isn’t nil, we assign its value to a local variable also named error, and then display its contents.
  5. If the error argument is nil, it means that no error occurred, and we display both the server response and the data received, in both raw and human-readable formats.
  6. Up until this point, we’ve only defined the data task. This statement activates it.

Turning the weather data into a Swift dictionary

Right now, if the weather request was successfully made and the data was successfully received, we take that data, convert it into a human-readable string, and output it to the debug console…

// Case 2: Success
// We got a response from the server!
print("Raw data:\n\(data!)\n")
let dataString = String(data: data!, encoding: NSUTF8StringEncoding)
print("Human-readable data:\n\(dataString!)")

…and that human-readable string looks something like this:

{"coord":{"lon":-82.46,"lat":27.95},"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"base":"cmc stations","main":{"temp":295.49,"pressure":1015,"humidity":64,"temp_min":294.15,"temp_max":296.15},"wind":{"speed":2.1,"deg":280},"clouds":{"all":1},"dt":1460163717,"sys":{"type":1,"id":728,"message":0.004,"country":"US","sunrise":1460200241,"sunset":1460245929},"id":4174757,"name":"Tampa","cod":200}

We could simply perform all sorts of string operations to extract the data we need, but why should we? The data is already in JSON format, which maps nicely to data structures in most programming languages, including Swift. There should be a simple way to take that incoming data and turn it into a nice Swift dictionary.

Enter the NSJSONSerialization class, which can convert JSON into Foundation objects (such as arrays and dictionaries), and vice versa. It has a method called JSONObjectWithData that takes two arguments:

  • data: An NSData object containing JSON data, which we happen to have as one of the parameters of our completion handler, and
  • options: Options that specify how the JSON data should be read and how the corresponding Foundation objects should be created.

Let’s change the code so that we no longer turn the data into a string, but instead using NSJSONSerialization‘s JSONObjectWithData method to turn it into a dictionary:

// Case 2: Success
// We got a response from the server!
do {
  // Try to convert that data into a Swift dictionary
  let weather = try NSJSONSerialization.JSONObjectWithData(
    data!,
    options: .MutableContainers) as! [String: AnyObject]

  // If we made it to this point, we've successfully converted the
  // JSON-formatted weather data into a Swift dictionary.
  // Let's print its contents to the debug console.
  print("Date and time: \(weather["dt"]!)")
  print("City: \(weather["name"]!)")
  
  print("Longitude: \(weather["coord"]!["lon"]!!)")
  print("Latitude: \(weather["coord"]!["lat"]!!)")

  print("Weather ID: \(weather["weather"]![0]!["id"]!!)")
  print("Weather main: \(weather["weather"]![0]!["main"]!!)")
  print("Weather description: \(weather["weather"]![0]!["description"]!!)")
  print("Weather icon ID: \(weather["weather"]![0]!["icon"]!!)")

  print("Temperature: \(weather["main"]!["temp"]!!)")
  print("Humidity: \(weather["main"]!["humidity"]!!)")
  print("Pressure: \(weather["main"]!["pressure"]!!)")

  print("Cloud cover: \(weather["clouds"]!["all"]!!)")

  print("Wind direction: \(weather["wind"]!["deg"]!!) degrees")
  print("Wind speed: \(weather["wind"]!["speed"]!!)")

  print("Country: \(weather["sys"]!["country"]!!)")
  print("Sunrise: \(weather["sys"]!["sunrise"]!!)")
  print("Sunset: \(weather["sys"]!["sunset"]!!)")
}
catch let jsonError as NSError {
  // An error occurred while trying to convert the data into a Swift dictionary.
  print("JSON error description: \(jsonError.description)")
}

If you run the app now, you’ll see that when put into dictionary form, it’s easy to extract weather data:

Date and time: 1462277829
City: Tampa
Longitude: -82.45999999999999
Latitude: 27.95
Weather ID: 800
Weather main: Clear
Weather description: clear sky
Weather icon ID: 02d
Temperature: 294.659
Humidity: 95
Pressure: 1025.47
Cloud cover: 8
Wind direction: 168.003 degrees
Wind speed: 2.11
Country: US
Sunrise: 1462272456
Sunset: 1462320359

Here’s what the complete WeatherGetter.swift should look like now:

import Foundation

class WeatherGetter {
  
  private let openWeatherMapBaseURL = "http://api.openweathermap.org/data/2.5/weather"
  private let openWeatherMapAPIKey = "YOUR API KEY HERE"
  
  func getWeather(city: String) {
    
    // This is a pretty simple networking task, so the shared session will do.
    let session = NSURLSession.sharedSession()
    
    let weatherRequestURL = NSURL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
    
    // The data task retrieves the data.
    let dataTask = session.dataTaskWithURL(weatherRequestURL) {
      (data: NSData?, response: NSURLResponse?, error: NSError?) in
      if let error = error {
        // Case 1: Error
        // We got some kind of error while trying to get data from the server.
        print("Error:\n\(error)")
      }
      else {
        // Case 2: Success
        // We got a response from the server!
        do {
          // Try to convert that data into a Swift dictionary
          let weather = try NSJSONSerialization.JSONObjectWithData(
            data!,
            options: .MutableContainers) as! [String: AnyObject]

          // If we made it to this point, we've successfully converted the
          // JSON-formatted weather data into a Swift dictionary.
          // Let's print its contents to the debug console.
          print("Date and time: \(weather["dt"]!)")
          print("City: \(weather["name"]!)")
          
          print("Longitude: \(weather["coord"]!["lon"]!!)")
          print("Latitude: \(weather["coord"]!["lat"]!!)")

          print("Weather ID: \(weather["weather"]![0]!["id"]!!)")
          print("Weather main: \(weather["weather"]![0]!["main"]!!)")
          print("Weather description: \(weather["weather"]![0]!["description"]!!)")
          print("Weather icon ID: \(weather["weather"]![0]!["icon"]!!)")

          print("Temperature: \(weather["main"]!["temp"]!!)")
          print("Humidity: \(weather["main"]!["humidity"]!!)")
          print("Pressure: \(weather["main"]!["pressure"]!!)")

          print("Cloud cover: \(weather["clouds"]!["all"]!!)")

          print("Wind direction: \(weather["wind"]!["deg"]!!) degrees")
          print("Wind speed: \(weather["wind"]!["speed"]!!)")

          print("Country: \(weather["sys"]!["country"]!!)")
          print("Sunrise: \(weather["sys"]!["sunrise"]!!)")
          print("Sunset: \(weather["sys"]!["sunset"]!!)")
        }
        catch let jsonError as NSError {
          // An error occurred while trying to convert the data into a Swift dictionary.
          print("JSON error description: \(jsonError.description)")
        }
      }
    }
    
    // The data task is set up...launch it!
    dataTask.resume()
  }
  
}

At this point, the WeatherGetter class doesn’t just get the weather data from OpenWeatherMap; it also puts that data into a form that we can process: a Dictionary. We’re still displaying the information in the debug console — we’re still not showing it to anyone who’s not running the app with Xcode.

In the next installment in this series, we’ll take the weather data, now in dictionary form, and make it visible to the user. We’ll also make it possible for the user to enter a city to get the weather for, rather than hard-wire it into the app.

xcode download

You can download the project files for this aricle (41KB zipped) here.

Categories
Uncategorized

“The Unbeatable Squirrel Girl”: The comic book that tips its hat to computer science

the unbeatable squirrel girl cover

Marvel Comics are doing some interesting things with characters that aren’t that well-known outside comic book fandom, not just with the Guardians of the Galaxy, a (very radically altered) Big Hero 6, and Ant-Man on the big screen and Jessica Jones, Peggy Carter, and various agents of S.H.I.E.L.D. on smaller ones, but even in their comic books, with Ms. Marvel and, more recently, the incredibly cute and unbeatable (it says right so in the title) Squirrel Girl.

Conceived as a throw-away character in the early ’90s when most comic book series were trying to be like The Dark Knight Returns, the 1982 Wolverine solo series, or the X-Men, Squirrel Girl has become important enough to merit her own book, The Unbeatable Squirrel Girl, written by Ryan North of Dinosaur Comics fame.

Ryan North has a computer science background, with a bachelor’s degree from Ottawa’s Carleton University and a master’s from the University of Toronto (that’s right, he’s Canadian). That background is what drives some of Squirrel Girl’s story; when she’s not fighting criminals and supervillains, she’s Doreen Green, first-year student (that’s a Canadianism; most Americans would say freshman) of computer science at Empire State University.

Sometimes her computer science studies are the backdrop, as in this scene, where she shows up a little bit late for her class on databases…

squirrel girl database class 1

squirrel girl database class 2

squirrel girl database class 3

…and other times, it plays a key role in defeating A-list supervillains like Victor von Doom. Doom’s primary flaw is that he’s a supreme egomaniac. Although he’s a science and engineering genius, he’s too proud to have learned programming languages that weren’t of his own design.

So when Squirrel Girl sends a message in C++ to her friends backing her up…

squirrel girl programming 1

Click the comic to see it at full size.

(By the bye, here’s the code that she called out…)

string lw(int arr[], int arrsize) {
  string ret = "";
  for (int i = 0; i < arrsize; i++) {
    ret += itoa(arr[i]);
    return ret;
  }
}

lw({90, 65, 80, 77, 69, 87, 84, 73, 77, 
69, 77, 65, 67, 72, 73, 78, 69, 80, 76, 
90}, 20) + "!!!!!";

…Doom doesn’t understand what she’s saying, since he only programs robots in his own “Doomsembly language” and never learned any real programming languages because it would mean learning from others…

squirrel girl programming 2

Click the comic to see it at full size.

Before you go spoiling the fun by saying “there’s no way you can formulate and yell out that code in that little time, and then have a friend do ASCII conversions in her head that quickly”, remember that all this is happening in a confrontation between a villain in a mechanical suit powered by both super-science and sorcery and a young woman with squirrel powers.

Also amusing: how the comic book often starts with Twitter conversations:

squirrel girl twitter

In case you’re wondering, the jingle she’s referring to is from the 1960’s Iron Man cartoon…

…and it gets referenced in the first Iron Man movie as his mobile phone ringtone…

The Unbeatable Squirrel Girl is a fun read, and the computer science bits just make it even more fun for a former computer science major like myself.

Categories
Uncategorized

Mobile news roundup: Procurement fraud, Mobile ate the world, US mobile network performance, and mobile electronic flight bags for pilots

Keeping an eye out for mobile device procurement fraud

 

mobile phone fraud

In the CFO.com article, Cell Phone Fraud: Who’s Watching IT?, corporate forensics specialists Jesse Daves and Celyna Frost talk about the very profitable business of mobile device procurement fraud. With aftermarket prices for a new iPhone 6S ranging from $1,000 in the U.S. to as much as $3,000 in China, it’s often tempting for people in IT departments to use their authority and access to procure mobile devices on their company’s behalf using company funds, make them disappear from the books and resell them at a completely cost-free profit.

Without the internal controls and systems to provide visibility into its inventory and procurement process, it’s much simpler for internal fraud. The article lists a number of “red flags” that indicate the potential for procurement fraud, including:

  • IT’s resistance to sharing access to the mobile provider’s billing web portal
  • When accounts payable receives only a summary of the mobile bill
  • Blanket charges that are simply summarized as “international data charges” or “roaming fees” without any substantiation
  • An unusual number of suspended or frozen accounts
  • Unusually large orders of devices
  • Recurring shipments to unknown parties

Suggestions for reducing the likeliness of mobile procurement fraud include:

  • Separating responsibilities so that employees with the authority to order equipment are not the same ones as those who receive them upon delivery
  • Controlling the process for payment approval and cost allocations (one fraud trick is to allocate costs for improperly-purchased goods to another business unit)
  • Maintaining comprehensive and complete records so that every item on every bill can be traced back to a device, circuit, or service in the company’s telecom inventory
  • Performing regular audits to ensure that all telecom charges can be connected to valid employees.

In the end, clear visibility into your telecom environment is your best defense against internal fraud.

Mobile Ate the World: A presentation by Andreesen Horowitz

Benedict Evans of $4 billion venture capital firm Andreesen Horowitz gave a presentation at The Guardian’s Changing Media Summit titled Mobile Ate the World, a play on his firm’s motto, “Software is eating the world”.

In it, he talks about how mobile is now the universal technology, scaling up to everyone on earth…

mobile is the new tech ecosystem

…how mobile isn’t just a screen size, but an ecosystem…

mobile is not a screen size

 

…and how mobile doesn’t just mean “mobile” — a lot of mobile use happens at home, and nearly 50% of smartphone traffic happens on wifi:

mobile doesnt mean just mobile

If you’re as interested in the future of mobile as we are, it’s worth reading Mobile Ate the World.

RootMetrics’ Mobile Network Performance in the US report

rootmetrics charts

The cellular carriers are in hot competition and expanding the reach of their LTE networks and grow their network capacities — how are they doing, and who’s offering the fastest and most reliable mobile experiences? The cellular analytics firm RootMetrics published regular reports on this topic, and their latest one looks at the service offered by AT&T, Sprint, T-Mobile, and Verizon in the second half of 2015.

ExpressJet replaces 50-pound flight bags with Surface tablets running Windows 10

pilot's flight bag

If you fly often, you’ve probably seen pilots walking to or from their flights lugging large bags like one pictured above (perhaps not as well-worn). These flight bags have traditionally carried a lot of paper documentation in binders: operating manuals, navigation charts, reference handbooks, flight checklists, logbooks and weather information, and together, they can weigh anywhere from 30 to 50 pounds. This documentation is updated regularly, so often before each flight, pilots have to collect updated documentation, remove the outdated material from their binders and insert the new pages. It’s a lot of paperwork to lug around and sort through; now imaging trying to find a key piece of information while you’re trying to fly a plane at the same time.

expressjet pilot and surface 3

As far back as 2011 — a mere year after the introduction of the iPad — airlines have been replacing all this paper documentation with “EFBs” (Electronic Flight Bags), which are tablets running apps specifically designed for pilots. United Airlines committed to deploying 11,000 iPads running Jeppesen’s FliteDeck app to pilots as their EFBs in the late summer of 2011, and more recently, ExpressJet got FAA approval to hand out Surface 3s running Windows 10 to their pilots to replace all that paper that went into their flight bags.

Here’s a video by Microsoft with ExpressJet pilot Renee Devereux talking about her new Surface 3 EFB:

The electronic flight bag is a good example of mobile devices playing to their strengths in the workplace:

  • As electronic replacements for large volumes of often-updated paper documents
  • Providing quick access to crucial data in routine and (literally!) mission-critical scenarios
  • Portable computing devices with significantly greater battery life than traditional laptops
  • An employee perk (as shown in the video, ExpressJet pilots are allowed to use their tablets to stay in touch with their families while on the “road”)

this article also appears in the GSG blog