farskiBuilding a Better Contact Sheet

farski posted on Monday, April 25th, 2011 | iPhone, Mobile | No Comments

Last week we decided to update the Photoshop file we provide to radio stations to allow them to customize the look of our core station iPhone app. There were two main problems with the version we had been using, the first being simply the organization of the layers. There was no standardized mapping of layers in the file to the individual files we need to use in the final app. The other problem was that our process for breaking the file down into its component parts was extremely time consuming. We were using an AppleScript that had been built in-house which extracted specific layers from the document, one-by-one. Additionally, we were maintaining low-res and high-res versions of the template for retina and standard displays.

The solution we decided to implement isn’t perfect, but it dramatically speeds up the processing step on our end, allows for a much more sensible organization of the component graphics within the document, and provides a buffer between what the station designer is doing on their end and what we’re doing on our end.

Buttons in the SpriteSheet

Buttons in the SpriteSheet

In order to ensure proper and meaningful organization of the template throughout the workflow, each graphical element we require from the stations is now represented as its own Smart Object. Each button, icon, background, etc is a distinct smart object. This way we can be sure that all changes being made to a graphic are in the appropriate and anticipated place. If our default icon is a single, raster layer but the station has a complex multi-layer vector replacement, there is no issue. Unlike the old version where new layers essentially went unaccounted for unless we were told explicitly that they had been added, now all the changes being made to each graphic are entirely encapsulated in a single object. This also allows us to set the canvas size on a per-graphic basis, so a designer doesn’t accidentally build a graphic that is too large for the space it will have in the final iPhone app.

Beyond that, the file is simply organized in a way such that relevant smart objects are in layer groups, so it’s easy for the designer to find what she is looking for. Icons are all in one place, backgrounds are in another, and status indicators another. All of the default objects are positioned roughly as they would appear in the final app inside a virtual iPhone, ensuring the designer is building the graphics in the correct context.

By using smart objects, we are also able to rethink the way the file is processed once it’s returned to PRX. Rather than run it through a script that is heavily dependent on specific layer names, we are now taking advantage of the dynamic Slice tool that Photoshop offers. You may be familiar with using Slice in Photoshop or Fireworks from when people were building websites with tables. It allows you to define contiguous regions of a file which can automatically be batch output, and additionally each slice can be given a unique name that persists inside the Photoshop file itself. The tool also allows slices to be dynamically linked to specific files in the file, and resizes to fit the contents of the layer. In our case, each smart object is a layer that has been linked to a slice, so if a station designer should choose to replace a default with an image that is larger or smaller, the slice we end up outputting is adjusted automatically.

Unfortunately, the slice tool is a relatively simplistic tool, and is only intended to work on the merged contents of the defined area. This is problematic, for instance, with toolbars, where we allow the designer to change both the background and the buttons. In our template we keep those graphics stacked on top of each other, just as they would appear in the app. The slice tool, though, would not handle that situation properly, and would export a single image rather than the separate parts.

Because we’re using smart objects, though, it’s trivial to duplicate each smart object somewhere else in the file where they can be arranged to prevent overlap. Duplicates of smart objects all point to the same source, so when the designer makes their changes in the part of the file where the layers are arranged to mimic the iPhone, the exploded view of the graphics we maintain behind the seems immediately reflects the changes.

Once we get the file back, we simply hide the designer-facing layers and bring up the matching layers we need for the batch export. A trip to the Save for Web dialog makes the export process take all of 10 seconds, orders of magnitudes faster than the old AppleScript. Since the names of the files being generated are being pulled from the slice metadata we ensure all of the station’s images will end up in the appropriate files we need to produce the iPhone app.

There are two caveats with this process. The first is that even though the the canvas size necessary for the user-facing layers is relatively small (technically just the resolution of a retina display), the actual file ends up being much larger. Because we need an unobstructed view of every single element, even when they are placed as closely together as possible the canvas ends up being about 4000×1500. This ends up being just empty space most of the time, and not really a major issue, but it is not ideal.

Because we will need to extract images through cropping, the canvas is much larger than the working area.

 

The other problem is something Photoshop is actually doing to give the user more control. Because smart objects can contain vector graphics, Photoshop allows them to be positioned at a sub-pixel level, even in the raster-based world of the actual Photoshop file. It does this even when the smart object contains only raster items itself. An unfortunate side effect of this is that unpredictable rendering can occur. Sometimes when the canvas height or width of a smart object is an odd number, Photoshop will try to center it inside the parent document, which places it halfway between real pixels. When that happens edge pixels of the smart object’s contents are improperly rendered (one edge is truncated a row early, and the edge pixels of the opposite edge are repeated). It’s not a hard problem to correct, but some care must be given since the entire document is based on smart objects.

farskiThe new Chris (aka Farski)

farski posted on Thursday, April 7th, 2011 | Introductions | No Comments

(this is a crosspost from the fabulous prx blog)

I’ve landed here at PRX just a month after discovering the company. I was immediately intrigued by the work they are doing with lots of the public radio content I have grown to enjoy and trust, so when I saw their posting for a Rails developer I had to jump on the opportunity. My recent work history being filled with Rails applications focusing on presenting data to users in the most effective ways possible. I’ve reached where I am through some print and web design, film and photo production, and even some financial services. Staying on top of the latest ideas and trends in technology, and thinking of ways to use them to help improve the world around us is something I’m passionate about.

PRX has brought me back to Boston, after graduating from the business school at Boston College in 2004. In my time there I worked hard to understand where uses of technology in business and media worked, and where they were lacking or not being used to their full potential. It’s amazing to be part of a company like PRX, which is at the forefront of enacting change in the storied world of public radio, bringing in a fresh generation of listeners and redefining the way radio content is delivered. I hope that with my background in user experience design and development I can help PRX continue to excel at reshaping public radio.

When I’m away from the computer, I pass the time playing a wide variety of board games, being a freelance sports photographerstaying pretty active, or hanging out with my dog. I’m always up for a good movie or documentary, and finding a new best-band-ever happens more frequently than it probably should.

rebeccaBuilding an iOS Application Platform

rebecca posted on Monday, March 21st, 2011 | Git, iPhone, Mobile | No Comments

In the last several months PRX introduced a new product to stations: an iPhone public radio station app platform. In the upcoming months the first several apps built on this platform will begin to appear in the iTunes app store. The goal with these apps is to provide a highly customizable application that allows stations to showcase their content and their brand. The challenge for the stations is that they are on constrained budgets and cannot pay the large app development costs usually associated with a custom built iPhone app. The challenge for us to is provide them with a satisfying alternative that has a full feature set, a custom feel, and a price tag that they can afford. To meet this challenge we’ve developed a platform that abstracts as much data as possible out of the application and streamlines the maintenance and updates of shared code between our applications. Here’s a laundry list of the techniques we’re using to accomplish this.

The Server Backend

We use a rails application backend server to maintain the data about the stations. This includes the information about their programs and their schedules as well as other app-related data such as the content of various HTML-based views that appear in the app. We also use this backend to integrate with third-party providers of data for the app, such as Publink.com which provides access to some stations’ member or listener discount systems. Using a backend server application makes it easy to update data in the app without a new application release to the iTunes store, offers the potential of letting stations maintain their own data, and helps us to standardize the models and formats of the data on which the iPhone code relies.

App Customization using Inheritance

After removing as much of the data (and the variations in the data formats) from the phone as possible, there still remains the problem of how to provide a core set of features and native views for the iPhone app but also to give stations a lot of leeway to customize the way their app looks and functions and to maintain the ability to provide improvements to features without breaking or overwriting customizations. We’re using inheritance to solve this problem. Each model, view, and controller in our app has both a “Base” version and a “Custom” version where the Base version is the parent class of the Custom version. We develop all features in the Base versions and expect clients not to make customizations or other changes within these files. That way when we update a Base version of a class we can push the change into all of the apps without fear of overwriting a customization. Throughout the code outside of the class we refer only to the Custom version of a class so that any customizations made in the custom version will be used instead of the code in the Base. This allows a station to make small changes to a particular area of their app or even to completely redo the way a particular area of the application works.

Managing Improvements Using git branches

One of the trickiest parts of keeping the platform development manageable was figuring out how to maintain the code bases for each app in a way that allows easy integration of improvements over time. We’re using git (and GitHub) for this purpose. We maintain a master version of the code as a main branch. It includes all of the features and the Custom classes but no customizations. Each station app has its own branch based on the master branch but including all of the customizations. When I’m developing, I always work in a specific station’s branch. When I make changes to Custom classes or non-shared resources I commit them in the station branch. When I make a change to Base classes or other shared code or resources, I commit in the master branch and merge back into the branch I’m working on. When it’s time to go to work on another station’s app, I check out the branch and the first thing I do is merge with the master branch to pull in the latest Base changes.

A cool side effect of this process is that GitHub maintains a helpful view of how up-to-date a given app is with the changes to Base as well as how customized an a given app is. Here’s a snapshot of that view right now:

Customized Graphics with Photoshop Contact Sheets

It was important to us and to our clients to work with their own designers to create a their look for their apps. In order to do this we abstracted out as many common and reusable user interface elements as we could and created a Photoshop “contact sheet” for the app. This contact sheet provides templates of the graphics that are used throughout the app separated into a single layer per item. We provide this contact sheet to our clients’ designers and they replace the default graphics with their own designs. This allows stations to use the defaults where they like but also to come up with their own design and look for the app. We then created an AppleScript that exports all of the images and saves them with the file names the app expects. This keeps the designer’s role strictly to design and limits the amount of time we as developers have to spend to incorporate the graphics into the app.

Using .strings Files for Text Customization

One other facet of customization worth mentioning, although we still haven’t quite worked out the kinks in it, is the repurposing of iOS internationalization features to do text customization within the app. Rather than using literal strings for text throughout the app, we pull the strings out of .strings files. This allows stations to provide their own “translations” for each bit of text in the app without having to make a customization within the code. I call this customization method half-baked because when we add new strings to the app it is best if we can regenerate the strings files which will cause them to be regenerated using the defaults specified in the application’s code. To avoid this we could add new strings in new .strings files, but this would result in a proliferation of these files over time.

chrisGit Hooks and Ruby

chris posted on Wednesday, March 16th, 2011 | Git, iPhone, Ruby | No Comments

Happy Wednesday, everyone! I don’t have very much time this week, so I’ll keep this short and sweet: While we’ve historically used Subversion at PRX, we have recently been migrating to Git to take advantage of some awesome tools and to better interact with the community.

We’re also most comfortable with Ruby, so when I was asked to look into setting up a build server for our iOS apps, there wasn’t much question as to how I would do it.

I set up a bare git repository running on a spare MacBook Pro with XCode and found the commands that were necessary to run when a new build was ready to be deployed. The next step was to set up the appropriate hook for that Git repository so that the builds could be triggered by a push.

In the SVN world, this would be a post-commit hook, but because Git works differently (one push can contain many commits), the hook we are interested in is the post-receive hook. You can take a look in your .git/hooks directory for some samples, most of which are written in sh. We wanted something in ruby, and here’s what we came up with:

#!/usr/bin/env ruby

require 'rubygems'
require 'grit'

repo = Grit::Repo.new(File.join(File.dirname(__FILE__), '..','..'))
while msg = gets
  old_sha, new_sha, ref = msg.split(' ', 3)

  commit = repo.commit(new_sha)

  case ref
  when %r{^refs/heads/(.*)$}
    branch = $~[1]
    if old_sha.to_i(16) == 0

      # A new branch was pushed

    else

      # A branch was updated

    end

  when %r{^refs/tags/}
    tag_object = Grit::GitRuby::Repository.new(repo.path).get_object_by_sha1(new_sha)
    tag = tag_object.tag
    tag_message = tag_object.message
    if old_sha.to_i(16) == 0

      # A tag was created

    else

      # A tag was moved

    end
  end
end

Simply save this in your .git/hooks/post-receive file and make it executable. Then, every time you push to this remote, the script will execute. You can make whatever modifications are necessary for your specific application.

I hope this helps everyone working with Git hooks and Ruby!

chrisWe’re Hiring a Software Developer

chris posted on Thursday, February 3rd, 2011 | Jobs | No Comments

This is a cross-post from the fabulous PRX Blog.

You: Live on planet earth, are human, creative and a motivated developer.
Us: PRX – Public Radio Exchange (prx.org); a super cool public media company in Harvard Square.

Job posting: Web/Rails/iPhone/Android/Whatever-comes-next Developer
Location: Harvard Square – Cambridge, MA
Type of Position: Full-time with benefits
Start date: Immediately
Telecommute: No

PRX’s mission is to help diverse voices and audio stories reach and inform the public through our innovative digital platforms, applications and services. We are a small team (12 full-time and another half dozen on contract) with big ambitions (transform public media, save the world) and an amazing network of users, partners, supporters, and collaborators. We are looking to hire an additional developer to help us build our next generation of mobile and web applications.

Required education, experience and skills:

  • We are looking for people who can develop well-designed, shipped and working software. Some combination of education and experience is required, such as an MSCS, prior work experience, internships, GSoC, or personal projects that have seen the light of day and scrutiny of users.
  • Experience with Rails/iPhone/Android development is valued but not essential. Interest in learning these and more is required; we are ready to invest in, teach, and support the right person in gaining necessary skills.
  • Ever write code to make a binary WAV file a byte at a time? Do you know how to make ffmpeg sing? We live and breathe public media; experience with media (audio, images, video) manipulation, encoding, streaming, playing or recording is a plus.

What we expect, and what you can expect:

  • We’ll ask you for your opinion and expect you to have one.
  • You have the ability to pick up new technologies in days and weeks not months and years.
  • We’ll have you create software with the languages and tools that best match the job.
  • You’ll refactor and improve existing applications, and build new ones from scratch.
  • We’ve got great sysadmin support but if you can build packages from source all the better.
  • You’ll be invited to contribute ideas to our operations and strategies as a whole.

We are looking for an enthusiastic and creative person, a developer with a passion for building robust, scalable applications with deceptively simple interfaces, and who is comfortable working in a dynamic environment.

You’ll work closely with a great team of developers and staff on all phases of the development cycle including planning, development, testing, deployment, and maintenance. This position reports to the Technical Director, Andrew Kuklewicz.

What we build:

For our web applications and backing our mobile apps with APIs, we use Ruby on Rails with MySql and JQuery, deploy to passenger on apache, use either (Thinking)Sphinx or Solr for search, and OpenID and OAuth for authentication. We are an early adopter and heavy user of Amazon Web Services, especially S3, EC2, and SQS. We have more than half a dozen Rails apps in production, and expect to create at least a few more this year alone (That’s where you come in).

For mobile development, we build for the iPhone (iPod Touch/iPad) and Android platforms, creating apps used by millions of public media fans. We built and maintain the ‘Public Radio Player’ and ‘This American Life’ iPhone apps (2.5+ million downloads), and have many more in the pipeline (When can you start?).

Work environment:

  • The excitement of an internet startup with a mission that matters, and services our users love.
  • In the heart of Harvard Square; high ceilings, big windows, bright walls and exposed beams, and – of course – a foosball table.
  • Shared office space with Harvard’s Berkman Center for Internet & Society and the fine folks at StopBadware.org
  • PRX received the MacArthur Award for Creative and Effective Institutions – the “genius” award for organizations. You’re a genius too!
  • PRX distributes The Moth, State of the Re:Union, Snap Judgment, Sound Opinions – and just about all the cool stuff in public radio.
  • We run REMIX, our own 24/7 channel on XM 136 , Internet and mobile stream, and on the air in Spokane, WA.
  • There are three accomplished cellists, a Korean rock star, semi-professional photographer, farmer, and a tap dancer on our staff.
  • If you’re into open source, audio, social software, public media, reinventing journalism, or all of the above, you are strongly encouraged to apply.

PRX has a fast-paced entrepreneurial environment, and developers need to be adaptable, flexible and persistent, with the ability to manage multiple tasks and communicate with the team about timelines and development priorities. It requires a person who is able to successfully maintain a complex suite of web applications for high uptime and reliability. The position requires technical and organizational skills, a commitment to the vision and mission of the Public Radio Exchange, and an understanding of its dynamic role as an emerging service in the public media field.

To Apply for this Opportunity
Please fill out this short form and provide your resume here: https://spreadsheets.google.com/viewform?formkey=dHdzMWotTGlybDFlLWpSNVJpNmVBTEE6MQ

  • Job location is Cambridge, MA

PRX is an equal Affirmative Action/Equal Opportunity Employer. Salary based on experience.

Come on in!

chrisAndroid Love: Part 1 of 2

chris posted on Thursday, February 3rd, 2011 | Android, Mobile | No Comments

Hey everyone! First, I want to apologize for what has been a much longer than anticipated break in posts on our technical blog. The tech team is keeping very busy, and it’s difficult to remember to make a post sometimes. That said, we know it’s very important for us to share what we are working on at a more technical level.

Recently, I’ve been getting to play with Android much more and it’s been making me very happy. Specifically, I have been working with the code provided by our Google Summer of Code student last year which will (very shortly!) become the Public Radio Player port for Android Smartphones. We’re very, very excited.

Force Close Dialog

Force Close Dialog. Oh No!

As I have been playing with the application, adding polish, and fleshing out functionality, I have run into a couple of situations where serious computation is being done on the UI thread. The application slows to a halt, and the user receives the dreaded Force Close dialog. No good.

In general, it’s a good idea to keep everything that does not deal directly with the UI on a separate thread. Unfortunately, because the Android UI framework is not thread safe, you can’t simply spin off threads that perform some long-running action and then update the UI; you need to actually tell the code living on the UI thread to update.

There are dozens and dozens of ways you can accomplish this, but there are only two that are appropriate if you want anyone to be able to read your code in the future. They’re useful in different situations, and they’re Handlers and AsyncTasks.

I’ll talk about AsyncTasks next week, but this week I will cover a pattern that is used all over Android, Handlers.

Android Handlers: How Do They Work?

Handlers basically allow interthread communication by allowing one to pass Messages back and forth. This means that you can create a Handler on the UI thread, fire up a new thread passing reference to your Handler, and do all of your UI stuff where it belongs.

Now, there are a couple of reasons why you might not want to use Handlers for everything. For one, they’re expensive (sort of) and they’re not the most readable way to handle background tasks. There are some best practices for working with Handlers which alleviate some of this, and I am going to scratch the surface here.

First, you should always use one Handler per Activity. Messages include an integer property called what, which is typically used to describe how the Handler should process the message with a switch statement:

Handler mHandler = new Handler(){
    @Override
    public void handleMessage(Message m){
        switch(m.what){
        case MESSAGE_1:
            doSomething(m.obj);
            break;
        case MESSAGE_A:
            doSomethingElse(m.obj);
        }
    }
}

You should also take advantage of the properties available in Messages as much as possible, rather than subclassing it. Check out the documentation for what properties are available.

For Example

Let’s take a look at using a Handler in the context of an Android Activity:


package org.prx.myapp;

import android.app.Activity;
import android.app.ProgressDialog;
import android.location.Location;
import android.os.Handler;
import android.os.Message;
import org.prx.myapp.LocationHelper;

class ShowLocationActivity extends Activity {

    protected final LocationHelper locHelper;
    protected final ProgressDialog mDialog;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg){
            switch(msg.what){
            case LocationHelper.LOCATION_OBTAINED:
                locHelper.calulateDistances((Location) msg.obj, this);
                mDialog.setMessage("Calculating distances...");
                break;
            case LocationHelper.DISTANCES_CALCULATED:
                mDialog.dismiss();
            }
        }
    };

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        if (locHelper == null) locHelper = new LocationHelper(this);
        mDialog = ProgressDialog.show(this, "", "Getting your location...", true);
        locHelper.obtainLocation(mHandler);
    }
}

In our LocationHelper class, we accept a Handler for each of the long running methods. Our calculateDistances() method might look something like the following:

public void calculateDistances(final Location loc, final Handler h){
    new Thread(new Runnable(){
        public void run(){
            /* Do some expensive calculation here */
            Message.obtain(h, DISTANCES_CALCULATED, null, null).sendToTarget();
    }).start();
}

This method starts up a new thread that then informs the main UI thread when the calculations are done. At no point is the main UI thread blocked, but we are still able to properly present the user with information about what is currently happening.

Handlers are not the Last Word

As I briefly mentioned earlier, there is another system available (called an AsyncTask) which provides an additional layer of abstraction for cases like this. I will go into those in detail next week, with a full working code example.

Thanks so much for reading, and if you have any questions, drop them in the comments below!

Tags: , ,

Andrew KuklewicziPhone Radio Apps Are Not Banned

Andrew Kuklewicz posted on Saturday, November 27th, 2010 | iPad, iPhone, Mobile | 8 Comments

UPDATE 11/28 4:45 PM:
Lance Venta of Radio Insight is following up on the possibility that AirKast may also have been banned as well. In the AirKast store where 277 apps are listed, the latest new release is dated 10/30. (Coincidentally, their last app was for ‘KNUE’, which is a station I grew up listening to in Tyler, TX.)

This would be a big deal, both because they have so many apps, but also because they have significant commercial partnerships (e.g. ESPN, Triton, Radio One which “primarily targets African-American and urban consumers” in 15 markets with 53 stations, Salem Communications “targeting audiences interested in Christian and family-themed content and conservative values” with 94 stations, Bonneville International with 26 stations, Citadel Broadcasting comprised of “165 FM stations and 58 AM stations”, & NextMedia with 33 stations.

I’ve started compiling a list of other providers possibly hit by this when I started this post; time to go back and see who else might have been affected by the policy. Statements from Apple specify that apps in a station’s own store should continue to be approved, but it will be interesting to watch the white-label app sellers’ stores, and see if they can add more station apps.

For example, Jacobs Media (with 249 apps in its store) has not had a new app in their own store since 11/10 (though as Lance pointed out to me, they have had updates as recently as 11/24). They have probably taken to putting all new apps in individual station stores in accordance with Apple’s policies (which they were previously doing with some station apps anyway).

For customers of white label app providers, in effect the price just went up by $100/year, as they now have to buy their own iOS Developer Account rather then riding on the app creator’s. For DJB Apps, with a price of $199.99 (1 platform, 1 station app), adding another $100 for Apple is not a minor difference.

Original Article:
We’ve been asked by a number of partners and acquaintances to weigh in on the recent controversy started by Jim Barcus’s letter to the editor in Radio Magazine.

The jist of the letter it that Apple rejected 10 of his iPhone apps because they no longer accept single stream/station apps:

On Nov. 10, 2010, we had 10 radio station apps rejected by Apple because Apple says “single station app are the same as a FART app and represent spam in the iTunes store” and Apple “will no longer approve any more radio station apps unless there are hundreds of stations on the same app.”

He does not identify a particular source at Apple (few can or do), or cite an official notification from them (such as the reason(s) that would be included in a rejection), but adds:

We have talked to many Apple reps about this, but they appear to have a script that they all read from saying that a single station app is not an enriching end user experience.

While this particular letter has engendered remarkable response (as it seems intended to do), the tale of a developer rejected is a common one. In fact, Brian Stormont had a similar odd rejection back in April (emphasis is mine):

Today I received the oddest rejection from Apple for a pair of iPhone apps I had submitted for two different radio stations. Apple rejected the apps with the explanation that they were of a similar “Family of radio applications” and “should be packaged in a single application using In App Purchase”.

I replied to Apple explaining how combining the two apps is not an option, but I haven’t yet heard back. I’m hopeful this isn’t the start of a new policy on Apple’s part prohibiting apps for individual radio stations.

UPDATE 4/13/2010: The two apps have now been approved, although I never received any clarification from Apple regarding my inquiry. The apps just suddenly became approved. Best I can assume is the original reviewer had made a mistake.

A point of interest is that this precedes Apple’s 9/9/2010 statement which accompanied the first set of official and public approval guidelines for the app store. This document makes clear that “We have over 250,000 apps in the App Store. We don’t need any more Fart apps. If your app doesn’t do something useful or provide some form of lasting entertainment, it may not be accepted.”, and shortly thereafter a point that perhaps Barcus missed, “If your app is rejected, we have a Review Board that you can appeal to. If you run to the press and trash us, it never helps.”

As with Barcus, Brian Stormont expressed (more skeptically) the fear that Apple is trying to cut down on the sheer number of radio apps, and instead focusing on aggregation apps that play an uncounted number of stations, as iTunes does for streams on OS X, or an actual radio does for broadcast.

If this were to happen, and Apple were to enforce a no single station apps policy, it would be immensely troubling to say the least.

The thing is, you shouldn’t believe it.

The app store right now is flush with single station apps, including many featured in ‘What’s Hot’ (such as ‘WMBR’ and ‘RadioU’), and ‘New and Noteworthy’ (‘TuneLab Radio’ appears as #7).
Surely if this were truly a blanket policy they would be rejecting these apps, not featuring them in such coveted spots.

There must be more to this, some of which came out when Trevor Long of your tech life also spoke with Apple:

I’ve spoken with Apple, as have several developers and the situation, while not crystal clear, is certainly very clear on principal. There is no ‘ban’ on Single station Apps.

My own summary is that App developers submitting identical apps with just a logo/stream change under their own developer accounts are not looked well upon. (and if you take the time to download a few of this chap’s apps, you’ll see how uninspiring they are, and similar too)

However, if a station has an app developed, and submitted under their own name, it should breeze through.

Likewise, if an individual or group create an app that links to a single station stream or show, it might face some hurdles.

From a station owner perspective I think that’s a good thing – but, from Apples point of view, good on them for ‘encouraging’ the development of rich apps with a user experience that is more than ‘just a stream’ – in the end, if it was ‘just a stream’ the industry won’t survive!

Moral of this story for Radio stations – be creative, own the rights, own the application submission.

Confirming this account and adding further detail is a translation of another conversation with Apple representatives:

Translation from German article in Radioszene.de:

http://www.radioszene.de/?p=18796

Faster than expected, Apple has reacted in a telephone call from german radio organization VPRT, This is a summary of the call:

“Apple will not delete any radio apps or prohibit access of radio apps to Apple Store. Apple suggests that every radio station makes their own developer account (79 Euro) and uploads their apps in there themselves. The apps can be developed by third parties (White label solutions). New and the apps in the future will be handled as so far. Apple confirmed, that several identical apps -which are provided from ONE developer account- will no more be accepted. (Comment: there has been some cases in the near past where a developer has submited hundred identical apps into the store). This rule is also applying to newspapers and other industries. If the app will be uploaded by the radio station this is no problem. Radio stations can also upload more than one app on their own developer account”.

Consistent with these posts, other radio app creators as or more prolific than Barcus have made it known they are not experiencing systematic rejections, nor are aware of any policy changes:

Claiming that Barcus is wrong, Paul Jacobs, VP/GM Jacobs Media/jacAPPS, tells RBR-TVBR that he’s been able to build radio station apps since Nov. 10: “Since that date, we have had apps for radio stations accepted as new as well as upgrades. And we are not alone. I invite you to go to the iTunes App Store and go into the “free” apps portion of the Music section. There you will see examples of dozens of radio stations – domestic, international, and Internet – that have been accepted and/or upgraded since November 10.”

Battle of the screen shots?
Jacobs even sent us a screen shot proving it. There were at least five radio stations — both AM and FM –with apps listed post-Nov. 10. Now, not to make any rash judgments here, but Barcus also sent RBR-TVBR a similar image, indicating the opposite was true.

Neither screen shots has been made public, but I have found results consistent with Paul Jacobs claim in my own perusal of the app store (I’ll leave this to you for homework).

UPDATE 11/27 12:05 PM: RBR.com has posted the screen shots. The one of the entire app store, sent by Jacobs, clearly shows many new radio apps. Barcus sent in list of apps by Jacobs Media (not what Jacobs invited users to look at), who has not published a new app since Nov 10. I have seen many Jacobs apps submitted in individual station accounts, so I tend to believe the Jacob’s claim that they have apps approved since the 10th, just not ones in their seller account.

Barcus’s letter seems aimed at causing uproar, positioning this as a conflict between Apple and the whole of radio. It now seems to be a more specific policy that has been applied to him (and perhaps other, less vocal, sellers).

It is unfortunate that other outlets, such as The Register and other sites added their voices to this uproar, and have yet to post corrections.

UPDATE 11/28: The Register and Martin Bryant from The Next Web have both updated their stories (thanks for the link Martin). The Register received a statement from Apple:

“There are many unique radio apps on the App Store and we look forward to approving many more,” reads a statement from an Apple spokesman sent to The Register. “One developer has attempted to spam the app store with hundreds of variations of essentially the same radio app and that is against our guidelines.”

This makes the 3rd communication from Apple confirming that this is an issue regarding a single developer, and a particular type of activity that Apple has previously described as a reason for app rejection (i.e. ‘spamming’).

As others have found Trevor’s post, they have reported this as a developer’s sour grapes rather than a draconian policy against radio, as Lance Venta did in Radio Insight, or in the corrected piece by Steve Safran in Lost Remote. That’s a wonderful retraction Mr. Safran; gracefully done, and with good humor – it ought to increase your readership (I know it did by at least one).

As the app store has reached a population of hundreds of thousands, Apple has been raising the bar on approvals, and you should expect this to continue as even more flock to the growing iOS platform. The best way to get your own apps approved it to start by providing apps people actually want (rich functionality and crafted interfaces). From there, you need to consider many factors in getting your apps approved, not to mention adopted, but that is the subject of my next post…

mattInteractive mobile app wireframes with OmniGraffle, PDF & GoodReader

matt posted on Friday, November 12th, 2010 | Mobile, OmniGraffle, Wireframes | 1 Comment

I’m late to the game in figuring out that the Action property existed in OmniGraffle but I did find what I think is a pretty cool way to create super quick, easy to build, interactive mobile app demos to test out concepts. I’ve been working quite a bit on the user experience side for our iPhone/iPad projects and I mentioned the awesome OmniGraffle iPhone and iPad stencils that I’ve been using in a previous post. When thinking about ways to test out some ideas we’ve been floating for the This American Life iPad app that we’ve been designing, I discovered the “Action” property for objects in OmniGraffle. This property gives us great power.

You’ll want to create multiple canvases in your demo document to really see the benefit.

Mini Tutorial

There isn’t much to it once you figure out the options. Create a new Document in OmniGraffle and draw an object. After selecting the object, open the inspector (Shift + Command + I). Open the properties dialog (Command + 2). The object will default to Geometry, which is the only view that I ever cared to check out until I stumbled on the Action dialog. Choose the Action view (third tab over for OmniGraffle Pro 5.2.3).

You should see something similar to this:

OmniGraffle Action Property dialog

OmniGraffle Action Property dialog

Note the Jumps Elsewhere option. When you have multiple canvases you can direct the users click action to another canvas, which can simulate your app functionality. In my demo here I’ve wired up the Home canvas New object/grouping to point to the News canvas.

Interactive PDF home screen

Interactive PDF home screen

Export as  PDF

Now that you have your actions wired up in OmniGraffle you can export the interactive wireframe as a PDF and share with the world. In OmniGraffle select (Option + Command + E) and choose the Format as PEF vector image and make sure the Export Area is Entire Document.

Running the demo on a device

After exporting the PDF I use the really nice Good Reader iPhone/iPad app to get the PDF on a device for demo purposes. It’s a paid app but it makes getting PDFs on the device super easy, supports the hyperlink/action functions and runs full screen without navigation chrome.

Downside

Lack of gesture support. Users have become accustomed to interacting with the iPhone and iPad using the swipe and pinch gestures. The PDF obviously doesn’t support that so there is a little setup when placing the demo in a users hands.

Resources

  • Sample PDF: interactive-pdf.pdf
  • Sample OmniGraffle file: interactive-pdf.zip
  • Tags: , , ,

    chrisPolymorphic Associations and Abilities

    chris posted on Monday, November 1st, 2010 | Rails, Ruby | 8 Comments

    I recently had a conversation with an old friend who is in the process of learning Ruby on Rails. He had run into a problem with polymorphic associations and I recommended he try something I had done for another project using polymorphic associations. It turns out that it was a good solution to the problem, and since I haven’t seen the pattern talked about elsewhere, I thought I should get it down on paper.

    For the sake of example, let’s say we’re building a Tumblr clone, where the polymorphic association lives inside of a Post model, and the different kinds of posts are all models unto themselves. We could use single table inheritance, but maybe the models vary enough or the storage method differs enough that that’s a bad idea. For that matter, Single Table Inheritance often just feels wrong.

    Simplicity will work best in this case, so let’s say that every post has a title, timestamps, and belongs to a user.

    # db/migrate/001_create_posts.rb
    class CreatePosts < ActiveRecord::Migration
      def self.up
        create_table :posts do |t|
          t.string :title
          t.references :user
          t.integer :postable_id
          t.string   :postable_type
          t.timestamps
        end
      end
    
      def self.down
        drop_table :posts
      end
    end
    # app/models/post.rb
    class Post < ActiveRecord::Base
      belongs_to :user
      belongs_to :postable, :polymorphic => true
    end
    

    Before we even get into the different kinds of posts we might want to make, let’s abstract this model so that we can tack it onto nearly any model in our application. How? A little bit of metaprogramming.

    # lib/postable.rb
    module Postable
      def self.included(klass)
        klass.instance_eval do
          has_one :post, :as => :postable
          alias_method_chain :post, :autocreate
    
          [:title, :user, :created_at, :updated_at].each do |method|
            delegate method, "#{method}=", :to => :post
          end
        end
      end
    
      def post_with_autocreate
        post_without_autocreate || build_post
      end
    end
    

    What does this get us? Well, in just a few lines of code, we have saved ourselves from really having to think about this problem very hard again. Consider creating two kinds of posts, something like a quote post and a freeform text post (called a blob, in this example):

    # db/migrate/002_create_quotes_and_blobs.rb
    class CreateQuotesAndBlobs < ActiveRecord::Migration
      def self.up
        create_table :quotes do |t|
          t.string :quotee
          t.text :quote
        end
        create_table :blobs do |t|
          t.text :content
        end
      end
    
      def self.down
        drop_table :quotes
        drop_table :blobs
      end
    end
    

    I have deliberately chosen separate interfaces for these two kinds of model so I can show off some other stuff later. But to get them posting, all we need to do is include our “Postable” module and we are up and running:

    # app/models/quote.rb
    class Quote < ActiveRecord::Base
      include Postable
    end
    
    # app/models/blob.rb
    class Blob < ActiveRecord::Base
      include Postable
    end
    

    That’s it. We can get started immediately by creating our forms. Because of the Postable interface we have created, both models will automatically have the fields on Post (and, in fact, will work transparently thanks to delegation). The only other thing we need to think about is creating a common interface back to the individual post types from the Post model. We can do this with a helper, the model, or we can take advantage of Rails’ partial rendering and just create a views/quote/_quote.html.erb and views/blob/_blob.html.erb. Those views might look something like:

    # app/views/blob/_blob.html.erb
    <h2>
      <%= blob.title %>
    </h2>
    <div class='byline'>
      by <%= link_to blob.user.name, blob.user %> on <%= blob.created_at %>
    </div>
    <div class='blob-content'>
      <%= blob.content %>
    </div>
    

    I’ll leave the quote partial as an exercise for the reader.

    At this point, we can put all of our posts on a single page like this:

    # app/controllers/posts_controller.rb
    class PostsController < ApplicationController
      def index
        @posts = Post.order_by('created_at DESC')
      end
    end
    
    # app/views/posts/index.html.erb
    <h1>All Posts</h1>
    <%- @posts.each do |post| %>
      <%= render post %>
    <% end -%>
    

    The same technique can be used in a number of situations, such as many kinds of authenticable users with one login screen or some other sort of shared attributes. What’s nice is that it is trivially extensible. You create a model with any extra fields that you need, include your module, and you’re up and running.

    mattUseful OmniGraffle stencils and templates for iPhone and iPad

    matt posted on Tuesday, October 19th, 2010 | iPad, iPhone, Mobile, Wireframes | 1 Comment

    I’ve been using OmniGraffle Pro for most of my iPhone and iPad wireframe jobs. I love the product, simple and easy to use. One of the things that I dig the most about it is the vibrant stencil and template community at http://graffletopia.com/. There are a number of stencils and templates that you can find out on the internet. The two that I’ve found to be most useful over the past few months are:

    They are well thought out and I’ve been able to find and modify just about any component I’ve needed.

    Categories & projects

    Archives