Skip to content

Instantly share code, notes, and snippets.

@Sakurina
Created August 2, 2010 22:42
Show Gist options
  • Save Sakurina/505460 to your computer and use it in GitHub Desktop.
Save Sakurina/505460 to your computer and use it in GitHub Desktop.
dumps CSV file of app name/bundle ID/retina display icon (if present)
#!/usr/bin/env cycript -p SpringBoard
/*
* ric - retina display icon data aggregator
*/
// App types
var CLASSIC_APP = 0;
var IPAD_ONLY_APP = 1;
var UNIVERSAL_APP = 2;
var UNKNOWN_APP = 3;
// 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;
}
var BUFFER = "App Name,Bundle Identifier[1],Icon Path/Filename (optional)\n";
// Actual runloop
for each (_icon in [[[SBIconModel sharedInstance] applicationIcons] allObjects]) {
var displayName = [_icon displayName];
var displayID = [_icon leafIdentifier];
var _app = [[SBApplicationController sharedInstance] applicationWithDisplayIdentifier:displayID];
var bundleID = [_app bundleIdentifier];
var _infoDict = _app.bundle.infoDictionary;
var _iconsList = [_infoDict objectForKey:"CFBundleIconFiles"];
var type = applicationType(_infoDict);
if ((type == CLASSIC_APP) || (type == UNIVERSAL_APP)) {
var fileName = undefined;
var bundlePath = [[[_app bundle] executablePath] stringByDeletingLastPathComponent];
// try the default default
if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath+"/Icon@2x.png"])
fileName = "Icon@2x.png";
// try default+@2x.png
if (!fileName) {
var defaultIcon = [[_infoDict objectForKey:"CFBundleIconFile"] stringByDeletingPathExtension];
var _2xIcon = defaultIcon+"@2x.png";
if ([[NSFileManager defaultManager] fileExistsAtPath:bundlePath+"/"+_2xIcon])
fileName = _2xIcon;
}
// try to guess which is the right one by filename
if (!fileName) {
var matches2x = [];
for each (f in _iconsList) {
if (![f hasSuffix:".png"])
f = f+".png";
if ([f hasSuffix:"2x.png"] || [f hasSuffix:"114.png"] || [f hasSuffix:"iPhone4.png"])
matches2x.push(f);
}
if ([matches2x count] >= 1)
fileName = matches2x[0];
}
// TODO? (desperate?) try a UIImage of each one and see if it's 114x114
// log it out if an icon was found
if (fileName)
BUFFER += displayName+","+bundleID+","+fileName+"\n";
}
}
[BUFFER writeToFile:@"/var/mobile/RetinaDisplayIcons.csv" atomically:YES];
#!/usr/bin/env cycript -p SpringBoard
RICSEL0 = new Selector("objectForKey:");RICSEL1 = new Selector("count");RICSEL2 = new Selector("containsObject:");RICSEL3 = new Selector("sharedInstance");RICSEL4 = new Selector("applicationIcons");RICSEL5 = new Selector("allObjects");RICSEL6 = new Selector("displayName");RICSEL7 = new Selector("leafIdentifier");RICSEL8 = new Selector("applicationWithDisplayIdentifier:");RICSEL9 = new Selector("bundleIdentifier");RICSEL10 = new Selector("bundle");RICSEL11 = new Selector("executablePath");RICSEL12 = new Selector("stringByDeletingLastPathComponent");RICSEL13 = new Selector("defaultManager");RICSEL14 = new Selector("fileExistsAtPath:");RICSEL15 = new Selector("stringByDeletingPathExtension");RICSEL16 = new Selector("hasSuffix:");RICSEL17 = new Selector("writeToFile:atomically:");CLASSIC_APP=0,IPAD_ONLY_APP=1,UNIVERSAL_APP=2,UNKNOWN_APP=3;function applicationType(e){var t;t=objc_msgSend(e,RICSEL0,"UIDeviceFamily");if(objc_msgSend(t,RICSEL1)==1&&t[0]==1)return CLASSIC_APP;if(objc_msgSend(t,RICSEL1)==1&&t[0]==2)return IPAD_ONLY_APP;if(objc_msgSend(t,RICSEL1)==2&&objc_msgSend(t,RICSEL2,1)&&objc_msgSend(t,RICSEL2,2))return UNIVERSAL_APP;return UNKNOWN_APP}BUFFER="App Name,Bundle Identifier[1],Icon Path/Filename (optional)\n";with({$cys:objc_msgSend(objc_msgSend(objc_msgSend(SBIconModel,RICSEL3),RICSEL4),RICSEL5),$cyt:undefined})for($cyt in $cys){_icon=$cys[$cyt];{displayName=objc_msgSend(_icon,RICSEL6),displayID=objc_msgSend(_icon,RICSEL7),_app=objc_msgSend(objc_msgSend(SBApplicationController,RICSEL3),RICSEL8,displayID),bundleID=objc_msgSend(_app,RICSEL9),_infoDict=_app.bundle.infoDictionary,_iconsList=objc_msgSend(_infoDict,RICSEL0,"CFBundleIconFiles"),type=applicationType(_infoDict);if(type==CLASSIC_APP||type==UNIVERSAL_APP){fileName=undefined,bundlePath=objc_msgSend(objc_msgSend(objc_msgSend(_app,RICSEL10),RICSEL11),RICSEL12);if(objc_msgSend(objc_msgSend(NSFileManager,RICSEL13),RICSEL14,bundlePath+"/Icon@2x.png"))fileName="Icon@2x.png";if(!fileName){defaultIcon=objc_msgSend(objc_msgSend(_infoDict,RICSEL0,"CFBundleIconFile"),RICSEL15),_2xIcon=defaultIcon+"@2x.png";if(objc_msgSend(objc_msgSend(NSFileManager,RICSEL13),RICSEL14,bundlePath+"/"+_2xIcon))fileName=_2xIcon}if(!fileName){matches2x=[];with({$cys:_iconsList,$cyt:undefined})for($cyt in $cys){f=$cys[$cyt];{if(!objc_msgSend(f,RICSEL16,".png"))f=f+".png";if(objc_msgSend(f,RICSEL16,"2x.png")||objc_msgSend(f,RICSEL16,"114.png")||objc_msgSend(f,RICSEL16,"iPhone4.png"))matches2x.push(f)}}if(objc_msgSend(matches2x,RICSEL1)>=1)fileName=matches2x[0]}if(fileName)BUFFER+=displayName+","+bundleID+","+fileName+"\n"}}}objc_msgSend(BUFFER,RICSEL17,"/var/mobile/RetinaDisplayIcons.csv",YES)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment