Skip to content

Instantly share code, notes, and snippets.

@Sakurina
Created May 30, 2010 17:44
Show Gist options
  • Save Sakurina/419189 to your computer and use it in GitHub Desktop.
Save Sakurina/419189 to your computer and use it in GitHub Desktop.
automated application icon data collection mechanism (don't be evil)
/*
* change - automated application icon data collection mechanism (don't be evil)
* by Yanik Magnan - http://r-ch.net
*
* LICENSE:
* Copyright (c) 2010, Yanik Magnan <[email protected]>
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* USAGE:
* cycript -p SpringBoard change.cy
*
* (Note that there will be no visible output unless your iPad is plugged
* into a USB port and is running iPhone Configuration Utility, or you're
* viewing your iPad's syslog directly.)
*
* DESCRIPTION:
* Basically, this script iterates through every application
* icon. It tries to identify what kind of app it is (classic,
* iPad, or universal), and from that, goes through the Info.plist
* and grabs the icon filenames/sizes, calling the logIcon function.
*
* From that point on, you can pretty much do whatever with it, like
* store the information in a local database, or send it off to a
* server. Whatever floats your boat.
*
* It currently does not handle defaults (using the default file names
* and not specifying them in the Info.plist) or apps with several role
* identifiers (Photos, MobileMusicPlayer), but handles many third-party
* apps well.
*
* Most of this was based on Tech Q&A QA1686 on Apple's developer site,
* which is public/non-NDA'd stuff.
*
* http://developer.apple.com/iphone/library/qa/qa2010/qa1686.html
*/
// App types
var CLASSIC_APP = 0;
var IPAD_ONLY_APP = 1;
var UNIVERSAL_APP = 2;
var UNKNOWN_APP = 3;
// Icon types
var APP_ICON_57 = "57x57 (iPhone Home)";
var APP_ICON_72 = "72x72 (iPad Home)";
var SPOT_ICON_29 = "29x29 (iPhone Spotlight/Settings, iPad Settings)";
var SPOT_ICON_50 = "50x50 (iPad Spotlight)";
// What type of application is this? (Unknown apps get skipped over.)
function applicationType(dict) {
var _supported = [dict objectForKey:"UIDeviceFamily"];
if (([_supported count] == 1) && (_supported[0] == 1))
return CLASSIC_APP;
if (([_supported count] == 1) && (_supported[0] == 2))
return IPAD_ONLY_APP;
if (([_supported count] == 2) && ([_supported containsObject:1]) && ([_supported containsObject:2]))
return UNIVERSAL_APP;
return UNKNOWN_APP;
}
// NSLog is just being loaded for logIcon to report /something/.
// If you run the script, look inside of iPhone Configuration Utility for the output.
NSLog_ = dlsym(RTLD_DEFAULT, "NSLog")
NSLog = function() { var types = 'v', args = [], count = arguments.length; for (var i = 0; i != count; ++i) { types += '@'; args.push(arguments[i]); } new Functor(NSLog_, types).apply(null, args); }
function logIcon(bundleID, iconName, type) {
// This is going to be the interesting part for most of you.
// It may be a better idea to add a displayName parameter eventually,
// come to think of it.
NSLog(@"Bundles/"+bundleID+"/"+iconName+" // " + type);
}
for each (_icon in [[SBIconModel sharedInstance] allIcons]) {
if ([_icon isKindOfClass:SBApplicationIcon]) {
var displayName = [_icon displayName];
var displayID = [_icon displayIdentifier];
var _app = [[SBApplicationController sharedInstance] applicationWithDisplayIdentifier:displayID];
var bundleID = [_app bundleIdentifier];
var _infoDict = _app.bundle.infoDictionary;
var _iconsList = [_infoDict objectForKey:"CFBundleIconFiles"];
switch (applicationType(_infoDict)) {
case CLASSIC_APP:
var legacyIcon = [_infoDict objectForKey:"CFBundleIconFile"];
if (legacyIcon)
logIcon(bundleID, legacyIcon, APP_ICON_57);
break;
case IPAD_ONLY_APP:
if (!_iconsList) {
var legacyIcon = [_infoDict objectForKey:"CFBundleIconFile"];
if (legacyIcon)
logIcon(bundleID, legacyIcon, APP_ICON_72);
break;
}
if (_iconsList.count >= 1)
logIcon(bundleID, _iconsList[0], APP_ICON_72);
if (_iconsList.count >= 2)
logIcon(bundleID, _iconsList[1], SPOT_ICON_50);
if (_iconsList.count >= 3)
logIcon(bundleID, _iconsList[2], SPOT_ICON_29);
break;
case UNIVERSAL_APP:
if (!_iconsList) {
var legacyIcon = [_infoDict objectForKey:"CFBundleIconFile"];
if (legacyIcon)
logIcon(bundleID, legacyIcon, APP_ICON_57);
break;
}
if (_iconsList.count >= 1)
logIcon(bundleID, _iconsList[0], APP_ICON_72);
if (_iconsList.count >= 2)
logIcon(bundleID, _iconsList[1], APP_ICON_57);
if (_iconsList.count >= 3)
logIcon(bundleID, _iconsList[2], SPOT_ICON_50);
if (_iconsList.count >= 4)
logIcon(bundleID, _iconsList[3], SPOT_ICON_29);
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment