mkale.com

Advertising

I generally dislike advertising, but why? And how much is ok?

I initially set out to categorize ads into two buckets. Those I called "passive" ads were ads alongside an app or web page or newspaper article or etc that I'm using, which can catch your eye but do not interfere with the main content. The others I called "active" advertising, which would be something like a TV commercial or splash screen ad that prevents you from using the main content for a short time to (hopefully) make you pay attention to the ad. But then I found a large grey area between them: those little dancing sprites in the corner of TV shows that advertise something. Or any squeaky flash ad that runs alongside the main content of a web page. Or anything really garish and bright that screams at you with colors if not sound, forcing you to look at it.

Instead, let's rank ads according to a spectrum of intrusiveness. A subtle line of text in a light font in the corner of a web page is less intrusive than several lines in a bolder font, is less intrusive than a small static image, is less intrusive than a big static image, is less intrusive than a slide-show of images, is less intrusive than a moving video, is less intrusive than an "interstitial". And different people are willing to tolerate different levels of intrusiveness.

I prefer services that have little or no ads, but not exclusively. I generally avoid live TV and radio because of (among other things) the ads. I instead watch TV on Netflix and listen to Pandora. The free Pandora does have ads but they are (to me) less intrusive than FM radio. For a commonly used app or service, I'd prefer to pay a bit rather than use a free service with ads. Though for a less commonly used app, bring on the ads. I read the print newspaper and some magazines, but generally toss out all the ads without reading through them. (I do of course glance at them as I'm doing this, and the ones that are on the same pages as the articles I can't help but look at.) I don't mind if the bus I'm riding on has a big ad on the side, or if the street I'm riding by has billboards on it. I think the bus and street would look better without them, but I'm happy making the compromise with my bus fare and the ad. Given a chance between paying the true cost of producing all that news content and taking the ads with my subscription, I'll keep the ads. Though I'd be interested to know what the cost would really be. What if the newspaper offered two subscription prices, one with ads and one without? I suppose this is what some newspaper websites do.

What would Times Square look like with no ads? Race cars? Soccer jerseys? Clearly we expect advertising in some places, and tolerate it in others. I also have no problem with advertising as a business model. If Google can make a zillion dollars by making a "free" email service (or video web site, or etc.) where the users really are the product, then that's fine with me as long as those users are happy with the arrangement. Android exists largely to allow Google to send ads to mobile users via lots of "free" apps. (I publish a few free, ad-supported, apps myself, on both Android and iOS, so I'm enjoying a bit of advertising as a business model.)

Advertising does diminish the quality of the product, at least a little bit. Or sometimes a lot -- the worst are those web sites which break up a one page article into five or fifteen "pages" so they can increase the number of (supposed) page views which they make their advertisers pay for. With any luck, one or both of consumers or advertisers will catch on to this and stop frequenting those kinds of pages. If I painted a big ad on the side of my house, I bet my neighbors would complain that the neighborhood looked worse for it.

Companies that push out a lot of ads (like Google and Facebook) will try to collect more and more information on us, so as to serve more relevant ads and charge advertisers more for the privilege. To some extent, this is ok -- I'd rather see an ad for a software development tool than for a thousand dollar gold watch that I'm never, ever, going to buy. Maybe you'd prefer the watch ad to the dev tool ad. But as technology allows these companies to gather and process more and more data on us, we're going into uncharted territory as to what they can do with it. Where do we draw the line? I'll probably draw it in a different place than you. I hope we're aware of when we cross that line.

What does the future hold? Advertising isn't going away. The intelligent advertisers will learn to make the most of the various mediums without annoying their audiences (too much). Some people will make money peddling products supported by advertising and some will make money by selling products directly. Same as it always has been. We as consumers of products or services should be aware of the various ways in which we're paying for them. Sometimes by cash out of pocket and sometimes by looking at ads. Sometimes both. Same as it always has been, at least as far back as published newspapers and likely even before then.

Leave a Comment

Windows Phone Code Sharing

I've been working on making two apps (lite and pro) based off a shared codebase. On iOS, I do this with a single Xcode project with two targets. I include most of the same source files in both targets and can build each one separately. For the few differences between the apps, I use compiler flags to #define a different constant in each target and can use different code as needed.

I tried to do something similar on Windows Phone. I created two separate .csproj files for the Lite and Pro projects, but had trouble including the same files in both of them. I wanted to include many of the same .cs source files but keep the .xaml different, and the files in the "Properties" directory different. (i.e., AssemblyInfo.cs and friends.) I wasn't able to rename the "Properties" directory and have it work correctly, nor was I able to references .cs files that lived outside of the directory containing the .csproj file correctly. It's possible I was doing something wrong here and there is a better approach, but this is what I came up with.

Top level directory contains .cs files for business logic, model classes, etc. As much as possible. It also contains the directories for each project, and the bulk of the code behind logic in files called (e.g.) "MainPageXamlShared.cs". It looks like this:

directory winphone/
Statistics.cs  (business logic)
Contraction.cs  (model class)
MainPageXamlShared.cs  (shared code-behind)
ContractionTimer/MainPage.xaml
ContractionTimer/MainPage.xaml.cs
ContractionTimer/Properties/...
ContractionTimer/ContractionTimer.csproj
ContractionTimerLite/MainPage.xaml
ContractionTimerLite/MainPage.xaml.cs
ContractionTimerLite/Properties/...
ContractionTimerLite/ContractionTimerLite.csproj
... more files of course

I'm leaving out a bunch of files but this gives you an idea. The MainPage.xaml in each directory are the full xamls (with differences between the two apps), but the code behind is entirely shared. MainPage.xaml.cs in each directory looks like this:

using Microsoft.Phone.Controls;

namespace ContractionTimer {
    public partial class MainPage : PhoneApplicationPage {
    }
}

That's it! All the logic is in the MainPageXamlShared.cs in the parent directory, which I was able to reference from each project with no trouble:

using Microsoft.Phone.Controls;
using System;
using System.Lots.More.Of.These;

namespace ContractionTimer {
    public partial class MainPage : PhoneApplicationPage {
        private readonly TimeSpan TIME_INTERVAL_SECONDS = TimeSpan.FromSeconds(1);
        // ...
        public MainPage() {
            InitializeComponent();
            // ...
        }
        // well, you get the idea ...
    }
}

This allows me to at least share the bulk of the code between two different versions of the app. A couple of final notes:

  • I know that Lite/Pro versions of apps are much less neeed on Windows Phone due to the very nice time-limited demo abilities of the platform. This works for many people but I wanted to do the traditional Lite/Pro versions for this app. That allows me to have a truly free (but ad supported) version that won't explode on people when they're in the middle of Labor. And my app is one that people might only use (intensly!) for a few hours and be done with, so the time-limited demo doesn't work as well here.
  • Please excuse my very basic understanding of Windows Phone. The other reason I started with a Lite (free) app is that I'm stil relatively new to the platform and don't (yet) want to make anyone pay for my Windows Phone apps. The last time I wrote serious code for a Windows platform, I was writing native C++ and COM based NT services that had no UI (but a lot of uptime!). I've got a lot of catching up to do in the last few years, including basically all of .NET, C#, Silverlight, XAML, and an alphabet soup of other things. I spend most of my time on iOS these days, what limited time I have after that on Android, and am attempting to work on Windows Phone here and there as a third platform. Visual Studio sure is nice though, that's one thing I've missed.
  • The method described above feels like a bit of a hack. If anyone knows of a better way to share code between a Lite and Pro Windows Phone app, please let me know!
Leave a Comment

iOS 5 and Blank UITableView section headers

I have an iOS app which uses UITableViews and custom section header views. Some of the sections are intended to be blank, so my -tableView:viewForHeaderInSection looked like this:


- (UIView*)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section {
    if (section == STATUSVC_SECTION_STATUS) {
        return nil;
    } else {
        return plainHeaderViewWithText(NSLocalizedString(@"Recent Entries", @"table view header"), tableView.bounds.size.width);
    }
}

where plainHeaderVIewWithText() is a funcion I've implemented like this. (I use it in more than one place).


UIView* plainHeaderViewWithText(NSString *str, CGFloat width) {
    UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, 35.0)] autorelease];
    [headerView setBackgroundColor:[UIColor chooseYourColorHere]];
    UILabel *headerText = [[[UILabel alloc] initWithFrame:CGRectMake(10.0, 3.0, width - 10.0, 18.0)] autorelease];
    headerText.font = [UIFont boldSystemFontOfSize:19.0];
    headerText.shadowColor = [UIColor grayColor];
    headerText.shadowOffset = CGSizeMake(0.0, 1.0);
    headerText.text = str;
    headerText.textColor = [UIColor whiteColor];
    headerText.backgroundColor = [UIColor clearColor];
    [headerView addSubview:headerText];
    return headerView;
}

Starting in iOS 5, though, I started getting unwanted blank headers that looked like this:

Not what I wanted! Looking at the UITableViewDelegate protocol docs, I noticed this bit:

The returned object can be a UILabel or UIImageView object, as well as a custom view. This method only works correctly when tableView:heightForHeaderInSection: is also implemented.

A hah! That must be it. Indeed, the docs for that method mention:

Prior to iOS 5.0, table views would automatically resize the heights of headers to 0 for sections where tableView:viewForHeaderInSection: returned a nil view. In iOS 5.0 and later, you must return the actual height for each section header in this method.

So, the fix is to include this method in my tableview delegate:


- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section == STATUSVC_SECTION_STATUS) {
        return 0.0;
    } else {
        return 22.0;
    }
}

This gets me back where I wanted to be:

Lesson learned: read the docs and implement the methods they tell you to, even if it looks like you don't need 'em!

Leave a Comment

Code Prettify

I installed the prettify module from google code so I can write about code here. Let's test it out! Just for fun, here are a few time helper functions that I use:

#include <time.h>

time_t midnightOnDay(time_t t) {
    struct tm theday;
    localtime_r(&t, &theday);
    theday.tm_hour = 0;
    theday.tm_min = 0;
    theday.tm_sec = 0;
    return mktime(&theday);
}

time_t todayMidnight() {
    return midnightOnDay(time(0));
}

bool areSameDay(time_t t1, time_t t2) {
    struct tm tm1, tm2;
    localtime_r(&t1, &tm1);
    localtime_r(&t2, &tm2);
    return ((tm1.tm_mday == tm2.tm_mday) && (tm1.tm_mon == tm2.tm_mon) && (tm1.tm_year == tm2.tm_year));
}

int daysBetween(time_t t1, time_t t2) {
    // we'll be rounding down fractional days, so set t1 to midnight and then do division
    time_t newt1 = midnightOnDay(t1);
    return ((t2 - newt1) / TWENTYFOURHOURS_SECONDS);
}

Let's see how this works!

Update November 4th, 3pm

I disabled the module temporarily while I work out the formatting.

Leave a Comment

Where's the iPod Touch?

Why is there still no Android / Windows Phone / WebOS / QNX version of the iPod Touch? A smart-phone sized device roughly equivalent to the current top-of-the-line phone, but without the phone. (And, crucially, without the montly data contract that goes along with it). One that runs most of the same apps as the phones and gives you much the same experience as the phones.

Apple has had an entry-level iOS device for years, which I'm sure has introduced many users and developers alike to the platform. I got my start writing iPhone apps because of an iPod Touch that I got in the summer of 2008. I'm now a small, independent mobile app developer and would love to write software for all these platforms. However, my budget does not justify five monthly data plans. I can't be the only one in this position.

Having a device is critical for two reasons. First, you need to test an app on real hardware before releasing it to users. The simulators / emulators are great for a quick code-build-test loop when doing major feature work, but nothing can replace actual hardware to test the performance and feel of an app. (Plus, the simulators and emulators can have bugs and different behavior from the devices too.)

The more subtle reason is that you really need to experience a platform before you can write software for it. Different mobile platforms have different UI paradigms, user expectations, different customs and beliefs. You don't know how to use the Android menu buttons, or the Windows Phone 7 tile patterns, or whatever it is that QNX has. Much the same as porting desktop apps between Windows and Mac OS X, you can easily tell when an app written for one platform has been ported straight across to another without really absorbing the UI paradigms of the new plaform. It doesn't feel right and the user experience is almost always bad.

To really get a feel for a new plaform, you have to use it -- see what the platform vendor and other third-party developers are doing. See how the plaform works first hand. You can't get those kinds of experiences from the simulator running on your desktop. Which brings me back to: where are the entry-level contract-less devices? If I could buy a sub-$300 device that ran Windows Phone 7 (or WebOS, or..) with the bulk of its features and apps, I would buy it in a heartbeat. And then I would be able to tinker with creating software for it. I'm smaller than most software development houses, who could likely afford to buy a handful of devices and the carrier contracts that go along with them before eating breakfast in the morning. But a lot of great apps have come from small independent developers who would think twice before doing this.

It's possible that hardware manufacturers don't see much profit in these devices. Indeed, looking at Apple's numbers, the total iPod market is much smaller than the iPhone market, and Tim Cook says that the iPod Touch is only about half of total iPod sales. Maybe HTC and Nokia look at those numbers and decide to pass. (Their profits would likely be even less than Apple's due to Apple's volume purchase agreements with component vendors.) But even if the hardware manufacturers don't see much/any profit in producing these devices, it should be in the platform vendors' interest that they exist. Couldn't Microsoft or Google give some incentive to HTC to produce such a device? And for HP and RIM who control their entire stack, couldn't they do it as a loss-leader for the platform? (Especially HP and RIM, who are having trouble getting developer adoption on their platforms.)

We're starting to see tablets from various manufacturers running various operating systems that don't require a carrier contract. They're not really competitive with the iPad yet, but they're getting there. Wouldn't it be nice to see smaller handheld devices that could compete with the iPod touch?

Leave a Comment

Comment Spam

On two occasions in the past month, I've gotten a burst of strange comment spam. First on my app website, and then a couple weeks later on my personal blog. The spam was unusual in that it didn't contain any offers for pills that alter the size of my waistline or other body parts, mail-order brides, mail-order college degrees, or whatever else the spammers are peddling these days. Instead, it consisted of short, pleasant-sounding thank-you type messages. Like the following:

  • Real brain power on display. Thakns for that answer!
  • That's not just the best ansewr. It's the bestest answer!
  • Superior thinking demonstrated above. Takhns!

And on and on like that. Each contains a misspelling, and there were other similarities as well:

  • They were all generic enough to apply (kinda) to any blog post
  • They all came from machines running Windows XP (though from various browsers)
  • They came in a bunch. I got about a dozen comments spread out across various blog entries all in the same day. Then a new wave hit my other blog in a similar manner, but again all in the same day.

I did some research, eventually finding this page, and a hackernews thread about it with people describing and talking about similar incidents.

Why the weird misspellings?

I imagine a common pattern for blog software is to put unknown commenters into a moderation queue but include a whitelist for previously known commenters, allowing them to post freely. So it's possible that the spammers start by sending some innocuous-looking comments, hoping to be allowed into the whitelist. Then, they come back and hit the website hard with spam comments once they are. The misspellings make those exact phrases rare on the web, which makes them easy to search for using search engines. The spammer might have a second-round piece of software that searches for blogs where their first-round comments got through, allowing them to focus further spam comments on those blogs where they are likely to be published. (I hope that by including the phrases above, I'm not going to trigger a wave of second-round spam!)

Why no links in the comments?

As above, it might be that the spammers save the links to enhancement pill websites for their second-round of comments, thinking that the first round is more likely to go through without them, allowing them into more whitelists. Another possible explanation is that my comment box does not have any "website" or "url" field. Many blogs allow commenters to include a link to their personal website and spammers might think that including their spammy links in those fields makes it less likely that the comments get filtered out. Their spamming software probably fills out web forms as completely as possible and then hits submit, not noticing that they never got a chance to leave their link as part of the comment.

Leave a Comment

What's going on here?

What's going on here and where is the old blog? First of all, the old blog still exists, you probably just stumbled over here by mistake. Click back over there and everything will be right with the world again.

But what's going on here? I spent a large portion of my time at Cisco writing. Emails. Specs. Documentation. Notes on the bathroom wall. That kind of thing. Since leaving Cisco I haven't been writing nearly as much as before. And I miss it. So I'm going to try to write some geeky things here every now and then as a form of practice. I like practice.

Will it be interesting? Probably not. Will it be frequent? Probably not! I've got a full time job as a stay at home Dad and a part time job as a mobile app developer. So that doesn't leave much time for writing geeky blog posts that no one's going to read. But I'll try to write a post or two occasionally when I can.

History | Blog | mkale.com