Advertise Mobile SDKs Books Events Forum News Social Networking Support Us
Follow @iphonedevsdk on Twitter

Interface 2, Advanced iOS
Mockup & Code Gen
($9.99)

Make your own iPhone apps
and run them live!
(free)

Pic Frame Dynamo: Photo Editing
($0.99)

Abiliator
(free)

Memory Hold'em: Heads Up
(free)

Want your application or service advertised on iPhone Dev SDK?

Go Back   iPhone Dev SDK Forum > iPhone SDK Development Forums > iPhone SDK Development

Reply
 
LinkBack Thread Tools Display Modes
Old 01-04-2010, 08:33 AM   #1 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: Helsinki
Posts: 304
fiftysixty is on a distinguished road
Default Finding out what Apps are installed

Hi,

I did a quick search on this but it pretty much came up empty. Is there a way to know which Apps are installed on a given device? I suspect this is impossible using the iPhone SDK, but how about in a Mac or Windows machine? It seems that the iTunes Music Library.xml file does not contain information about the Apps, or at least I couldn't find my installed Apps in the file. Obviously there is the Mobile Applications -folder, but it contains all the apps I've purchased, with seemingly no information about which are actually installed on my iPhone. Looks like AppsFire is able to pull out that information from somewhere, anybody know how they do it?
fiftysixty is offline   Reply With Quote
Old 01-04-2010, 10:40 AM   #2 (permalink)
Registered Member
 
Join Date: Sep 2009
Posts: 57
kdp8791 is on a distinguished road
Default

Quote:
Originally Posted by fiftysixty View Post
Hi,

I did a quick search on this but it pretty much came up empty. Is there a way to know which Apps are installed on a given device? I suspect this is impossible using the iPhone SDK, but how about in a Mac or Windows machine? It seems that the iTunes Music Library.xml file does not contain information about the Apps, or at least I couldn't find my installed Apps in the file. Obviously there is the Mobile Applications -folder, but it contains all the apps I've purchased, with seemingly no information about which are actually installed on my iPhone. Looks like AppsFire is able to pull out that information from somewhere, anybody know how they do it?
I highly doubt you will be able to do something like this and if you were to find a way to do so, the application you create to do that will more than likely be rejected by Apple.
__________________
kdp8791 is offline   Reply With Quote
Old 01-04-2010, 11:51 AM   #3 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: Helsinki
Posts: 304
fiftysixty is on a distinguished road
Default

Quote:
Originally Posted by kdp8791 View Post
I highly doubt you will be able to do something like this and if you were to find a way to do so, the application you create to do that will more than likely be rejected by Apple.
I'm not looking for ways to do it by violating the SDK agreement, but I suspect it might be possible on the desktop side of things, at least AppsFire seems to do it. I just don't know how they do it. Obviously you can scan the Mobile Applications directory to get a rough list of all Apps one has downloaded but then you need a way to parse the filenames to correct App names, and you still don't know which Apps are actually installed. Knowing which Apps are installed would be cruicial in utilizing custom URL schemes for App interoperation. Right now, without a way to know if an App is present it is quite pointless to have Apps communicating together.
fiftysixty is offline   Reply With Quote
Old 01-04-2010, 12:27 PM   #4 (permalink)
Senior Member
iPhone Dev SDK Supporter
 
Join Date: Nov 2009
Posts: 179
thewitt is on a distinguished road
Default

Though it won't help you to "browse" the App directory and see what's installed on the iPhone, canOpenURL will let you test to see whether or not you can use a specific App URL scheme before actually trying it out in your code.

-t
thewitt is offline   Reply With Quote
Old 01-04-2010, 02:39 PM   #5 (permalink)
Shmoopi LLC
 
Shmoopi's Avatar
 
Join Date: Jun 2009
Location: Virginia
Posts: 213
Shmoopi is on a distinguished road
Default

Quote:
Originally Posted by kdp8791 View Post
I highly doubt you will be able to do something like this and if you were to find a way to do so, the application you create to do that will more than likely be rejected by Apple.
That's wrong, their is a way to check if an application is installed or not, however, it does violate the Sandbox rules and Apple *may reject your app for using this. But it has been done before by other Apps that are available in the App Store, so feel free to try it

Sometimes you may want to check if a specific app is installed on the device, in case you use custom URL schemes that require some other app to be installed (you could just gray out/disable some buttons then). Unfortunately, Apple apparently does not have any function that checks this for you, so I whipped one up. It does not enumerate every single app, instead it uses the MobileInstallation cache which is always up-to-date with SpringBoard and holds the Info dictionaries of all apps installed. Although you're not "supposed" to access the cache, it's readable by App Store apps. Here is my code which at least works perfectly fine with the Simulator 2.2.1:
Code:
// Declaration
BOOL APCheckIfAppInstalled(NSString *bundleIdentifier); // Bundle identifier (eg. com.apple.mobilesafari) used to track apps

// Implementation

BOOL APCheckIfAppInstalled(NSString *bundleIdentifier)
{
	static NSString *const cacheFileName = @"com.apple.mobile.installation.plist";
	NSString *relativeCachePath = [[@"Library" stringByAppendingPathComponent: @"Caches"] stringByAppendingPathComponent: cacheFileName];
	NSDictionary *cacheDict = nil;
	NSString *path = nil;
	// Loop through all possible paths the cache could be in
	for (short i = 0; 1; i++)
	{
	
		switch (i) {
	case 0: // Jailbroken apps will find the cache here; their home directory is /var/mobile
		path = [NSHomeDirectory() stringByAppendingPathComponent: relativeCachePath];
		break;
	case 1: // App Store apps and Simulator will find the cache here; home (/var/mobile/) is 2 directories above sandbox folder
		path = [[NSHomeDirectory() stringByAppendingPathComponent: @"../.."] stringByAppendingPathComponent: relativeCachePath];
		break;
	case 2: // If the app is anywhere else, default to hardcoded /var/mobile/
		path = [@"/var/mobile" stringByAppendingPathComponent: relativeCachePath];
		break;
	default: // Cache not found (loop not broken)
		return NO;
		break; }
		
		BOOL isDir = NO;
		if ([[NSFileManager defaultManager] fileExistsAtPath: path isDirectory: &isDir] && !isDir) // Ensure that file exists
			cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
		
		if (cacheDict) // If cache is loaded, then break the loop. If the loop is not "broken," it will return NO later (default: case)
			break;
	}
	
	NSDictionary *system = [cacheDict objectForKey: @"System"]; // First check all system (jailbroken) apps
	if ([system objectForKey: bundleIdentifier]) return YES;
	NSDictionary *user = [cacheDict objectForKey: @"User"]; // Then all the user (App Store /var/mobile/Applications) apps
	if ([user objectForKey: bundleIdentifier]) return YES;
	
	// If nothing returned YES already, we'll return NO now
	return NO;
}
Here is an example of this, assuming that your app is named "yourselfmadeapp" and is an app in the app store. 
Code:
NSArray *bundles2Check = [NSArray arrayWithObjects: @"com.apple.mobilesafari", @"com.yourcompany.yourselfmadeapp", @"com.blahblah.nonexistent", nil];
for (NSString *identifier in bundles2Check)
	if (APCheckIfAppInstalled(identifier))
		NSLog(@"App installed: %@", identifier);
	else
		NSLog(@"App not installed: %@", identifier);
Log Output:
Code:
2009-01-30 12:19:20.250 SomeApp[266:20b] App installed: com.apple.mobilesafari
2009-01-30 12:19:20.254 SomeApp[266:20b] App installed: com.yourcompany.yourselfmadeapp
2009-01-30 12:19:20.260 SomeApp[266:20b] App not installed: com.blahblah.nonexistent
Try this out before using it, I think Apple changed where the MobileInstallation.plist is located and if you do change it, try it out on an actual device not the simulator. Good Luck!

Trackback for this code goes to:
iDevKitCode Sample: Check if an app is installed -
iPhoneDevSDK: Is it possible to retrieve these information?
Shmoopi is offline   Reply With Quote
Old 01-04-2010, 06:32 PM   #6 (permalink)
Registered Member
 
Join Date: Nov 2009
Location: Helsinki
Posts: 304
fiftysixty is on a distinguished road
Default

Thank you very much for the suggestions, I think I have enough to get moving now. I'm a bit reluctant to go ahead with a method that could at some point cause rejection, and since canOpenURL will be sufficient for my needs, I think I'll end up using it. I don't want to be forced to change my App later on if an update gets caught in the review process.
fiftysixty is offline   Reply With Quote
Old 01-06-2010, 01:13 PM   #7 (permalink)
Registered Member
 
Join Date: Jan 2010
Posts: 1
metronomadic is on a distinguished road
Default

Quote:
Originally Posted by Shmoopi View Post
That's wrong, their is a way to check if an application is installed or not, however, it does violate the Sandbox rules and Apple *may reject your app for using this. But it has been done before by other Apps that are available in the App Store, so feel free to try it

Sometimes you may want to check if a specific app is installed on the device, in case you use custom URL schemes that require some other app to be installed (you could just gray out/disable some buttons then). Unfortunately, Apple apparently does not have any function that checks this for you, so I whipped one up. It does not enumerate every single app, instead it uses the MobileInstallation cache which is always up-to-date with SpringBoard and holds the Info dictionaries of all apps installed. Although you're not "supposed" to access the cache, it's readable by App Store apps. Here is my code which at least works perfectly fine with the Simulator 2.2.1:
Code:
// Declaration
BOOL APCheckIfAppInstalled(NSString *bundleIdentifier); // Bundle identifier (eg. com.apple.mobilesafari) used to track apps

// Implementation

BOOL APCheckIfAppInstalled(NSString *bundleIdentifier)
{
	static NSString *const cacheFileName = @"com.apple.mobile.installation.plist";
	NSString *relativeCachePath = [[@"Library" stringByAppendingPathComponent: @"Caches"] stringByAppendingPathComponent: cacheFileName];
	NSDictionary *cacheDict = nil;
	NSString *path = nil;
	// Loop through all possible paths the cache could be in
	for (short i = 0; 1; i++)
	{
	
		switch (i) {
	case 0: // Jailbroken apps will find the cache here; their home directory is /var/mobile
		path = [NSHomeDirectory() stringByAppendingPathComponent: relativeCachePath];
		break;
	case 1: // App Store apps and Simulator will find the cache here; home (/var/mobile/) is 2 directories above sandbox folder
		path = [[NSHomeDirectory() stringByAppendingPathComponent: @"../.."] stringByAppendingPathComponent: relativeCachePath];
		break;
	case 2: // If the app is anywhere else, default to hardcoded /var/mobile/
		path = [@"/var/mobile" stringByAppendingPathComponent: relativeCachePath];
		break;
	default: // Cache not found (loop not broken)
		return NO;
		break; }
		
		BOOL isDir = NO;
		if ([[NSFileManager defaultManager] fileExistsAtPath: path isDirectory: &isDir] && !isDir) // Ensure that file exists
			cacheDict = [NSDictionary dictionaryWithContentsOfFile: path];
		
		if (cacheDict) // If cache is loaded, then break the loop. If the loop is not "broken," it will return NO later (default: case)
			break;
	}
	
	NSDictionary *system = [cacheDict objectForKey: @"System"]; // First check all system (jailbroken) apps
	if ([system objectForKey: bundleIdentifier]) return YES;
	NSDictionary *user = [cacheDict objectForKey: @"User"]; // Then all the user (App Store /var/mobile/Applications) apps
	if ([user objectForKey: bundleIdentifier]) return YES;
	
	// If nothing returned YES already, we'll return NO now
	return NO;
}
Here is an example of this, assuming that your app is named "yourselfmadeapp" and is an app in the app store. 
Code:
NSArray *bundles2Check = [NSArray arrayWithObjects: @"com.apple.mobilesafari", @"com.yourcompany.yourselfmadeapp", @"com.blahblah.nonexistent", nil];
for (NSString *identifier in bundles2Check)
	if (APCheckIfAppInstalled(identifier))
		NSLog(@"App installed: %@", identifier);
	else
		NSLog(@"App not installed: %@", identifier);
Log Output:
Code:
2009-01-30 12:19:20.250 SomeApp[266:20b] App installed: com.apple.mobilesafari
2009-01-30 12:19:20.254 SomeApp[266:20b] App installed: com.yourcompany.yourselfmadeapp
2009-01-30 12:19:20.260 SomeApp[266:20b] App not installed: com.blahblah.nonexistent
Try this out before using it, I think Apple changed where the MobileInstallation.plist is located and if you do change it, try it out on an actual device not the simulator. Good Luck!

Trackback for this code goes to:
iDevKitCode Sample: Check if an app is installed -
iPhoneDevSDK: Is it possible to retrieve these information?
I don't mean to be a pain, but I'm a newbie trying to work my way through an introductory iPhone programming book, and I'd really like to be able to enumerate apps if possible. Can you tell me how I'd achieve that using this com.apple.mobile.installation.plist technique, or at least point me in the right direction? I was considering a desktop app that could look at all of the apps that are being synced, but it looks to me like the best I could manage with that would be all of the downloaded apps (i.e., I can't find any info on which ones are synced).

Thanks in advance for any help you can provide.!

Cheers,
-m
metronomadic is offline   Reply With Quote
Reply

Bookmarks

Tags
app, installation, iphone, itunes


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



» Advertisements
» Online Users: 204
8 members and 196 guests
andeh89, Domele, Fstuff, LEARN2MAKE, nanaeq20, revg, Rudy, SillyHoney
Most users ever online was 1,387, 04-10-2012 at 04:21 AM.
» Stats
Members: 180,048
Threads: 95,622
Posts: 409,223
Top Poster: BrianSlick (8,152)
Welcome to our newest member, songyo64
Powered by vBadvanced CMPS v3.1.0

All times are GMT -5. The time now is 11:52 PM.
Powered by vBulletin® Version 3.8.0
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.
Search Engine Friendly URLs by vBSEO 3.3.0