Ramblings of an iPhone developer
Windows Phone Please

I went to the AT&T store today. I really wanted to love the Lumia 900. I really wanted to. I had played with the Lumia 800, but since it’s not an “official” US WinPhone, I figured I’d check out the 900 and see how it is.

Why, Nokia, did you screw this up. I’m not going to dive into another Lumia 900 review like the rest of world has over the few days. Why I’m mad at Nokia is that they obviously caved to pressure from AT&T (and possibly Microsoft) to build the 900 on the cheap. Someone, somewhere, thought that the best way to gain traction in the smartphone market was to build a phone that is cheaper than the iPhone. The side effect? A phone that just doesn’t feel premium. The Lumia 800 feels premium and next to the iPhone, I would even argue that (except for the inane charge port), it actually feels BETTER.

Instead, they built a phone that feels less polished, is too big for the average hand, with a sub-par screen for the size and some major design issues (like the “nub” around the screen). The phone feels like it’s targeting the Samsung Galaxy and Moto Droid phones.

Note to Nokia: Wrong target.

Fine, maybe it will grab some share from Android, but it won’t garner the insane profits that the premium iPhone does for Apple or the cache that it has. It will become another phone and OS that will eventually get swallowed up by the overwhelming number of Android devices that are just blah. Nokia would have been smarter to start in the premium space.

Sad.

Stupid iPhone Mockups

Why are blogs and media sites obsessed with publishing ridiculous mockups of what the next iPhone might look like? I know it feeds traffic to the sites and the Apple devoted gobble it up (I’m guilty of clicking through some of them), but many of them are just downright stupid.

Take this one for instance: http://www.idownloadblog.com/2012/04/02/iphone-pro-concept/

First, it’s ugly. Second, anyone with any sense of what photography is all about will know that if you want to build a good high-end digital camera, don’t use a sensor crammed into a cell phone. DSLRs are bulky for three main reasons:

  1. The curtain/mirror takes space. With live-view cameras, this is becoming less critical, but traditional curtains take space.
  2. A high quality sensor still needs space and power. Don’t try to cram it into millimeters of space.
  3. Proper center of gravity is critical to good photography. If you can’t balance the camera well, you can’t do anything advanced with shutter speed and aperture.

If someone REALLY wanted to build a great iPhone/camera integration, forget using the lens or sensor in the phone. They are great portable devices and are ideal replacements for a point and shoot. Instead, build a proper body that has a great sensor and a dock built in so that the camera can use the phone for what it’s good for:

  1. An amazing screen that can do wonders for live-view and shot reviews.
  2. Excellent computing power for image adjustments in camera.
  3. Constant connectivity for sharing shots, geo-locating, etc.
  4. Top-notch touch screen responsiveness for high quality UIs for managing the camera.

Let the Nikons and Canons of the world build great camera bodies, sensors and lenses and let Apple build top notch portable devices and OSes.

And don’t get me started on in-car infotainment systems. What a gold mine for true iPhone/iPad integration.

Post-Jobs Apple

The blogosphere has been alive with chatter about Apple as of late – The release of the new iPad, the announcement about dividends and stock buybacks, etc. Many of the articles, tweets and podcasts inevitably make comments about how Apple is changing and this or that is something that Steve Jobs never would have done – that since Jobs’ passing, Apple has changed. The conversation then segues to speculations about what Apple would be like if Steve Jobs were still alive and how sad it was that Jobs did not treat his cancer aggressively.

Those of you who have read the Jobs biography know that there was quite a bit of focus on Jobs pension for alternative medical treatment. When he was diagnosed with cancer, he opted to try diet and lifestyle changes as opposed to surgical intervention to treat the cancer. Ultimately, they didn’t work and the cancer had progressed to a point where surgery and any other modern medical treatments would not have helped. Some people go as far as to say Jobs killed himself.

I’ve dealt with my own serious medical issues in recent years and when faced with these hard decisions, I opted for aggressive medical intervention. That decision was a good one as I am healthy and alive. But that decision was not unusual for me. I am a relatively conservative and pragmatic person and deciding on modern medical procedures was a pragmatic and logical solution to a problem.

What if Jobs had made that same decision and opted for surgery when his doctors recommended it? He’d probably still be alive today and running Apple. But there’s a flip side to that. If Jobs had opted for surgery, he probably would have had a different personality and many of the crazy, game-changing… even world changing decisions that he made throughout his life likely never would have happened.

So which is better – a world that still has Jobs but doesn’t have the innovations and world-changing technologies that we enjoy today or to have lost Jobs early and live in a world that he envisioned as far back as the late 70s.

My guess is his argument would have been that “it’s better to burn out than to fade away.”

Sparrow for iPhone

Today, the excellent developers of Sparrow for Mac released a new mail client for the iPhone. Being an avid Sparrow for Mac user, I immediately installed the app to give it a run.

Before I get flamed for my comments here, I fully recognize that the issues I raise are more Apple’s API issues and not the design or implementation of the app by the Sparrow team.

The design of the app is beautiful and effortless. It feels just like the Mac app - making navigating through emails and interacting with them simple and easy. The visuals of the app are professionally produced and look great on a retina display.

My two major issues with the app lie in it’s handling of the mail itself.

First, there is no Exchange support. Now, I know that the Mac version also doesn’t handle Exchange mail, but on a desktop environment, that’s acceptable. Most people are used to the idea of having one mail client for personal mail use and one for work mail. But on a mobile device, users need access to all of their email in one place. The jarring experience of hopping from one app to another for corporate email is just unpleasant. This is also my major issue with Android’s mail system.

Second, Sparrow for iPhone can use the native backgrounding capabilities to set up local notifications to check mail periodically. That’s great… once the app has been started after a respring. There are many users that reboot their devices daily and to have to open up the app and wait for it to load new email is just not a pleasant experience. I should be able to open the app and see my new mail immediately because it’s already been loaded. Additionally, there are no push notifications built into the app (apparently due to privacy concerns by the Sparrow team - legitimate) which forces me to open the app just to see if I have mail.

Like I said at the beginning, both of these issues are really more attributable to the lack of good messaging APIs in the Apple SDK - having developed LockInfo, I know how the Apple system works - it’s just not public. And this is where I start to feel cheated by the Sparrow team.

The Sparrow team knows that there is no SDK for them to work with the mail subsystem on iOS. There was a time when this was true for calendar events and when that was true, there were no custom calendar apps. At some point, Apple decided to add EventKit which allowed for the development of a myriad of custom calendar apps - both good and bad. I feel like Sparrow is taking advantage of their buzz and the lack of trials in the App Store to make a quick buck - instead of developing a half baked mail app, they should have used their clout in the Mac app world (Sparrow for Mac is very popular) to influence Apple to open up a MessageKit SDK for interacting with the mail subsystem on iOS. Just like EventKit, Apple is smart enough to build a stable, safe SDK for interacting with mail - why not push them to do it before developing the Sparrow client.

As an example of how mail could be done differently on the iPhone, Sparrow for iPhone is a great app. As an example of how to affect change in the iOS ecosystem and to get Apple to open up more APIs, I think it’s a failure and a huge missed opportunity for the Sparrow team.

Comex in Cupertino

In a week rich with Apple news, comex, jailbreak prodigy, is going to work for Apple as an intern. Congratulations, comex. You deserve this!

There’s a lot of speculation as to what he might do there and how this will affect the jailbreak community. It would be pretty naive to think that Apple doesn’t plan to focus comex’s unique skills on security, allowing him to root out potential bugs and holes in iOS before they reach the public. It’s also a foregone conclusion that comex will not be the developer that releases the next iOS jailbreak (seems like a bit of a conflict of interest).

So what does this mean for jailbreaking in the iOS5 world?

There’s no question that the jailbreak community is losing one of it’s shining stars. That will have some impact on our ability to get new jailbreaks. Will his (probable) focus on security at Apple make it harder to jailbreak in the future? Possibly. Will it mean the end of jailbreaking? Unlikely.

If you look back through the history of jailbreaks, they don’t (usually) happen overnight (unless it’s a known vulnerability that Apple couldn’t close up). Jailbreakers have the luxury of time. If Apple releases an iOS update, jailbreakers have weeks, even months sometimes, to find a vulnerability, exploit it and package up a jailbreak. And even if Apple releases a new OS version the next day, people who care about jailbreaks will just sit back and wait for the next vulnerability to be discovered.

Apple is a software company that has millions of customers, only a small fraction of which jailbreak. Apple can not sit around for weeks, possibly months, for a security team to analyze every attack vector to determine if there is a vulnerability in there. They need to get the new OS out to stay competitive in the market. There may be less vulnerabilities to work with, but there will be one that the jailbreakers will find and exploit.

As long as there is an interest in jailbreaking, there will be a vulnerability that can be exploited to permit it.

Thank you, Mr. Jobs, for changing the world.

Thank you, Mr. Jobs, for changing the world.

Yesterday, Steve Jobs officially resigned as CEO of Apple. In the last 10 years, under Jobs’ leadership, Apple has successfully launched not one, not two (IMHO) but six industry changing technologies:

  1. iPod
  2. OSX
  3. iOS
  4. iPhone
  5. iPad
  6. Macbook Air

Obviously, based on my particular interests, 2007’s introduction of the iPhone was the real tipping point for consumer electronics. There have been several recent graphics of what consumer electronics, particularly music players, phones and portable computers looked like before Apple’s products entered the market, and the shift is pretty drastic. You forget when you have one in your pocket every day what it was like just five years ago. And when you have a young child who, at three years old, can navigate an iPhone/iPad effortlessly, you realize that the world as they know it will be a very different place.

So, again, thank you, Mr. Jobs. Your imagination, intuition and dedication have change the world, and my life.

iOS5, Notification Center and LockInfo

I had the privilege of sitting front and center (7th row) at the keynote for WWDC11.  All was great and exciting through the whole Lion presentation, and then came iOS5.  First on the list was notifications.  Cue punch in the gut.  If imitation is the sincerest form of flattery, Apple must have a teenage crush on me, because Notification Center looks an awful lot like LockInfo (in some ways).

The twittersphere (at least my small corner of it) has been active with questions about how this affects LockInfo.  In short:

It doesn’t.

Apple finally figured out that you need to do more than show a big blue popup on the lockscreen to provide users with useful information.  What they added is a direct rip off of Peter Hajas’ MobileNotifier (at least he got hired by Apple).  But what is it missing (at least based on early views… I’ll admit I don’t have the developer seed yet):

  1. No emails on the lockscreen.  (Redacted… screenshot shows it)
  2. No quick previews.
  3. No direct replies via integrations with other apps.
  4. No status bar icons.
  5. No plugin API.
  6. No weather (on the lockscreen).
  7. No RSS feeds.
  8. No Twitter integration.
  9. No Facebook integration (coming soon).
  10. No favorites quick dial/text/facetime.

It does look pretty though.  No sarcasm, it does look pretty.

Now, let’s slide to unlock iOS5.  Notification Center implements a drop down “info shade” from the status bar in any app (don’t know if you can do it on SpringBoard).  Again, it looks nice, but:

  1. No quick previews.
  2. No direct replies.
  3. etc, etc, etc…

And what about seeing that information on your SpringBoard itself.  Nope, not there. 

So, really, what does this mean to LockInfo… seriously, not much.  I plan to continue to develop and innovate LockInfo and I’ll plan to be at WWDC12 for them to copy me again.

WeatherIcon Themes and Configuration

By default, the icon uses the first weather location defined in your iPhone’s Weather app to load the weather information.  You can change this in the preferences.  The preferences are located at /var/mobile/Library/Preferences/com.ashman.WeatherIcon.plist.

{{{
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0”>
<dict>
        <key>OverrideLocation</key>
        <false/>
        <key>Location</key>
        <string>20852</string>
        <key>Celsius</key>
        <false/>
        <key>ShowFeelsLike</key>
        <false/>
        <key>ShowWeatherIcon</key>
        <true/>
        <key>ShowStatusBarImage</key>
        <false/>
        <key>ShowStatusBarTemp</key>
        <false/>
        <key>UseLocalTime</key>
        <false/>
        <key>RefreshInterval</key>
        <integer>15</integer>
        <key>WeatherBundleIdentifier</key>
        <string>com.apple.weather</string>
</dict>
</plist>
}}}

  * OverrideLocation - Boolean setting for whether to use the Apple weather application settings or the settings in this file.  Defaults to false, meaning use the Apple weather application.  The first location from the Apple weather application will be used.
  * Location - Zip code or location code for your location.  This is the code that is used by Yahoo! Weather to find your location.  Look at http://developer.yahoo.com/weather/ for pointers on finding your code.
  * Celsius - Boolean setting for whether to show Celsius temperature.  Defaults to false.
  * ShowFeelsLike - Boolean setting for whether to show the wind chill temperature.  Defaults to false.
  * ShowWeatherIcon - Boolean setting for whether to show replace the weather icon with the “live” weather.  Defaults to true.
  * ShowStatusBarImage - Boolean setting for whether to show the weather image in the status bar.  Defaults to false.
  * ShowStatusBarTemp - Boolean setting for whether to show the temperature in the status bar.  Defaults to false.
  * UseLocalTime - Boolean setting which tells the icon whether it should make an additional web service request to determine an accurate local time for the weather location for determining night/day.  Defaults to false, which means the update time in the weather feed itself is used.
  * RefreshInterval - Number of MINUTES between update.  Defaults to 15 minutes.
  * WeatherBundleIdentifier - The bundle identifier of the application you use for weather.  Defaults to the standard iPhone weather app, com.apple.weather.

=Themeing=
The theme configuration is located at {THEME}/Bundles/com.apple.springboard/com.ashman.WeatherIcon.plist.  This is theme specific and controls how the images and text are rendered.

{{{
<?xml version=”1.0” encoding=”UTF-8”?>
<!DOCTYPE plist PUBLIC “-//Apple//DTD PLIST 1.0//EN” “http://www.apple.com/DTDs/PropertyList-1.0.dtd”>
<plist version=”1.0”>
<dict>
        <key>ImageScale</key>
        <real>1.0</real>
        <key>ImageMarginTop</key>
        <integer>1</integer>
        <key>LockInfoImageScale</key>
        <real>0.5</real>
        <key>StatusBarImageScale</key>
        <real>0.5</real>
        <key>TempStyle</key>
        <string>color: black; text-align: left;</string>
        <key>TempStyleNight</key>
        <string>color: lightgray;</string>
        <key>StatusBarTempStyle</key>
        <string>color: black;</string>
        <key>StatusBarTempStyleFSO</key>
        <string>color: lightgray;</string>
        <key>ShowWeatherIcon</key>
        <true/>
        <key>ShowStatusBarImage</key>
        <true/>
        <key>ShowStatusBarTemp</key>
        <true/>
        <key>Mappings</key>
        <dict>
               <key>weather24</key>
               <string>light_rain</string>
        </dict>
</dict>
</plist>
}}}

  * —Type— - Type is deprecated in version 1.8.x.  Look at the Mappings section for details on how to map icons.  The Klear Weather Icon theme can be used as an example for mapping kweather themes.
  * ImageScale - This float is multiplied by each weather image to scale the image down to the right size for the icon.
  * ImageMarginTop - Defines the number of pixels from the top of the icon the image should be rendered.
  * ImageScale - This float is multiplied by each weather image to scale the image down to the right size for the LockInfo plugin.
  * StatusBarImageScale - This float is multiplied by each weather image to scale the image down to the right size for the status bar.  Status bar images should be between 14 and 16 pixels in height.
  * TempStyle - CSS style for the temp text.  There is a default style but you can override it with this setting.
  * TempStyleNight - CSS style for the temp text at night.  This style is additive on top of the other TempStyle attribute.
  * StatusBarTempStyle - CSS style for the temp text in the status bar shown in applications (light gray background by default).  There is a default style but you can override it with this setting.
  * StatusBarTempStyleFSO - CSS style for the temp text in the status bar on the home screen and lock screen (black background by default).  There is a default style but you can override it with this setting.
  * ShowWeatherIcon - Optional boolean setting for whether to show replace the weather icon with the “live” weather.  Defaults to true.
  * ShowStatusBarImage - Optional boolean setting for whether to show the weather image in the status bar.  Defaults to false.
  * ShowStatusBarTemp - Optional boolean setting for whether to show the temperature in the status bar.  Defaults to false.
  * Mappings - This is an optional dictionary that can define mappings between “default” filenames and custom filenames.  More details below.

==Images==
Images are located in {THEME}/Bundles/com.apple.springboard.  WeatherIcon supports rendering separate backgrounds from weather icons.  Finding an image follows this algorithm:

{type}{code}_{day/night}.png

where type is either “weather”, “weatherstatus” or “weatherbg” for weather images, status bar images or backgrounds, respectively.  For example, to find the weather image for weather condition code 32 during daylight hours, the icon will look for:

  # weather32_day.png
  # weather32.png
  # weather_day.png
  # weather.png

FYI - If you do not define status bar specific images and you have the setting turned on, the regular weather images will be used.

The theme plist lets you map the default filenames above to custom filenames.  You can map really any portion of the name.  Do not include the “.png” though.  That is inferred.  For example, you can map all weather images to a custom image named “foobar.png” by adding:
{{{
<key>weather</key>
<string>foobar</string>
}}}
Or you can map just a single night weather image for a code:
{{{
<key>weather34_night</key>
<string>foobar_night</string>
}}}
Let’s say you have a day and night foobar image.  You can map it once with:
{{{
<key>weather34</key>
<string>foobar</string>
}}}
The icon code will append the night and day suffix for you.

LockInfo SDK

SDK Download

A LockInfo plugin starts with a plugin controller. A plugin controller is responsible for initializing a plugin and setting the datasource and delegate for the LockInfo table view.

@protocol LIPluginController <NSObject>
-(id) initWithPlugin:(LIPlugin*) plugin;
@end

LIPlugin is an object defined by LockInfo to give the controller access to preferences and other metadata about the plugin.

@interface LIPlugin : NSObject

@property (nonatomic, retain) id<UITableViewDelegate> tableViewDelegate;
@property (nonatomic, retain) id<UITableViewDataSource> tableViewDataSource;

// basic metadata about plugins
- (BOOL) enabled;
- (BOOL) native;
- (NSString*) bundleIdentifier;
- (NSBundle*) bundle;
- (NSBundle*) globalBundle;
- (NSDictionary*) preferences;
- (NSDictionary*) globalPreferences;
- (NSArray*) managedBundles;

// API calls for previews
-(UIView*) showPreview:(UIView*) content;
-(void) dismissPreview;

@end

During initialization, the plugin controller needs to register the table view delegate and data source that LockInfo should use to load data and handle callbacks for the LockInfo table view. The delegate and data source should follow the same rules as any standard iPhone SDK table view.

Notifications

At init time, the plugin controller should also register for notifications that it cares about.

// update with...
static NSString* LIUpdateViewNotification = @"com.ashman.LockInfo.updateView";

// respond to...
static NSString* LIUndimScreenNotification = @"com.ashman.LockInfo.screenUndimmed";
static NSString* LITimerNotification = @"com.ashman.LockInfo.timerFired";
static NSString* LIViewReadyNotification = @"com.ashman.LockInfo.viewReady";
static NSString* LIPrefsUpdatedNotification = @".prefsUpdated";
static NSString* LIBadgeChangedNotification = @".badgeChanged";
static NSString* LIApplicationDeactivatedNotification = @".applicationDeactivated";

There are two different types of notifications listed above. You’ll notice that some are fully-qualified notification names and some are just the last part of a notification name. The difference lies in whether the notification is generic for LockInfo or app/plugin specific. For example, all plugins can respond to the generic “undim screen” notification with LIUndimScreenNotification. Additionally, a particular plugin could respond to an application closing with LIApplicationDeactivatedNotification, where the notification is prefixed with the bundle identifier of the application that closed.

-(id) initWithPlugin:(LIPlugin*) plugin
{
self = [super init];
self.plugin = plugin;
self.dataCache = [NSMutableDictionary dictionaryWithCapacity:10];
self.iconCache = [NSMutableDictionary dictionaryWithCapacity:10];

self.daysView = [[[WIForecastDaysView alloc] init] autorelease];
self.iconView = [[[WIForecastIconView alloc] init] autorelease];
self.tempView = [[[WIForecastTempView alloc] init] autorelease];

plugin.tableViewDataSource = self;
plugin.tableViewDelegate = self;

NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(update:) name:LIViewReadyNotification object:nil];
[center addObserver:self selector:@selector(updateOnUpdate:) name:@"WIWeatherUpdatedNotification" object:nil];
[center addObserver:self selector:@selector(refreshWeather:) name:[plugin.bundleIdentifier stringByAppendingString:LIBadgeChangedNotification] object:nil];

return self;
}

LIUpdateViewNotification is a notification that goes the opposite direction. Plugin controllers should post this notification, with the plugin as the object, to the default notification center. This will trigger LockInfo to update the view with updated data. The notification can include data in the userInfo which will be sent to an HTML theme if you wish to support HTML themes (more on this later).

-(void) updateWeather:(NSDictionary*) weather
{
if (!self.plugin.enabled)
return;

// Do some stuff to load the weather...
...

NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:weather, @"weather", nil];
[[NSNotificationCenter defaultCenter] postNotificationName:LIUpdateViewNotification object:self.plugin userInfo:dict];
}

TableView DataSource/Delegate

@protocol LITableViewDataSource <UITableViewDataSource>

@optional
// Custom datasource methods for showing the correct counts on the screen.
-(NSInteger) tableView:(LITableView*)tableView numberOfItemsInSection:(NSInteger)section;
-(NSInteger) tableView:(LITableView*)tableView totalNumberOfItemsInSection:(NSInteger)section;

// Custom method for manual refreshes
-(void) tableView:(LITableView*)tableView reloadDataInSection:(NSInteger)section;

@end
@protocol LITableViewDelegate <UITableViewDelegate>

@optional
// Custom methods for getting the icon and detail for the headers of the sections.
-(NSString*) tableView:(LITableView*) tableView detailForHeaderInSection:(NSInteger) section;
-(UIImageView*) tableView:(LITableView*) tableView iconForHeaderInSection:(NSInteger) section;

// Method for creating a preview
-(UIView*) tableView:(LITableView*) tableView previewWithFrame:(CGRect) rect forRowAtIndexPath:(NSIndexPath*) indexPath;

@end
Themes for LockInfo 3.0

Long delayed, but here are the details on themes for LockInfo 3.0.  I made a significant shift in the way themes are handled to reduce dependence on WinterBoard and to allow for different themes in the different LockInfo views (lockscreen, homescreen and InfoShade).  As a result, the structure of a theme has changed significantly.

Core LockInfo Themes

Themes are now stored in /Library/LockInfo/Themes in a separate directory per theme.  LockInfo 3.0 ships with four themes built in.  Each theme is composed of a series of images used by LockInfo to render the view:

  • LICellBG.png - A background for each cell in the LI table.  *This is currently not used.*
  • LICountBG.png - A background image for behind the count/refresh/delete icon for each section header.
  • LIDelete.png - Icon for deleting a cell.
  • LIHeaderBG.png - Background image for each section header.
  • LILargeHeaderBG.png - 96px tall header background for larger section headers.
  • LIRefresh.png - Icon for refreshing a section.
  • LIRepeatAlert.png - Icon shown over the section icon to represent that there is a repeat alert registered for the section.
  • LISectionDelete.png - Icon for deleting an entire section.  This is shown over the LICountBG.png.
  • LISubheaderBG.png - Background image for subheaders (i.e. day titles in the Calendar plugin).

All of these images are retina aware, so themes should include @2x versions of each image.

The theme is controlled by a Theme.plist file stored in the same directory.  The plist is composed of three style blocks (header, summary and detail) plus a background color and a icon set indicator.

Each style is a “dict” composed of six options:

  • FontName - (string) The name of the font to use.  Defaults to the system font.
  • FontStyle - (string) Plain (default), bold, italic.
  • FontSize - (integer) Point size for the font.
  • TextColor - (string) Color description composed for four floats (red, green, blue, alpha) ranging from 0 to 1.
  • ShadowColor - (string) Color description for the shadow following the same format as TextColor.  If not set, there is no shadow.
  • ShadowOffset - (string) X and Y offset for the shadow in pixels.  Defaults to 0,0.

You can set the background color using the same color format as TextColor and ShadowColor.  BackgroundColor defaults to black (0,0,0,1).  

Finally, the SectionIconSet indicator is used in the same way as the technique UIKit uses for status bar indicators.  The indicator can be either Black (default) or Silver and is used to prefix image lookups for section icons.  This allows different images to be shown as the section icon depending on the theme.

Plugin Themes

Each LockInfo 3.0 theme can contain elements that are applied to specific plugins.  This allows each plugin to have customized icons and headers based on the active theme.  The themes are handled with image names by convention:

<image>_<plugin identifier>[@2x].png

Therefore, to customize the header for the mail plugin, you would create an image called “LIHeaderBG_com.ashman.lockinfo.MailPlugin@2x.png”.  Right now, only the headers and sectionIcons are supported, but more will be available in the future.