Commits

Jeff Laing committed 2b2bf9e

Silence the log message about how we should be passing an options dictionary to AMDeviceLookupApplications()
Slightly clunky API to maintain backward compatibility. If people don't like our default list of attributes, they override a property on the device.

Comments (0)

Files changed (2)

MobileDeviceAccess.h

 	NSString *_bundleid;
 }
 
-/// Return the internal dictionary that contains all our information
+/// Return the internal dictionary that contains all our information.  Note that
+/// the application may be incomplete since it is filtered by the attributes listed
+/// in the applicationAttributes member of the AMDevice object.
 - (NSDictionary*) info;
 
 /// Return the name (usually) visible in the Springboard.  To get the actual name
 	NSString *_lasterror;
 	NSString *_deviceName;
 	NSString *_udid;
-	
+	NSArray *_applAttributes;
+
 	bool _connected, _insession;
 }
 
 /// The same value may be retrieved by passing \p "SerialNumber" to \p -deviceValueForKey:
 @property (readonly) NSString *serialNumber;	// "5984999T14P"
 
+/// Returns the array of attributes that will be requested for when using the
+/// installedApplications method. If nil, we use a "reasonable set".
+@property (retain) NSArray *applicationAttributes;
+
 /// Create a file service connection which can access the media directory.
 /// This uses the service \p "com.apple.afc" which is present on all devices
 /// and only allows access to the \p "/var/mobile/Media" directory structure
 /// as the user 'mobile'
 - (AFCCrashLogDirectory*)newAFCCrashLogDirectory;
 
-
 /// Create a file service connection rooted in the sandbox for the nominated
 /// application.  This uses the service \p "com.apple.mobile.house_arrest" which is
 /// present on all devices

MobileDeviceAccess.m

 // mach_error_t AMDeviceValidatePairing(am_device device);
 // 000037e6 T _AMDeviceUnpair (am_device)
 
-mach_error_t AMDeviceLookupApplications(am_device device, CFStringRef apptype, CFDictionaryRef *result);
+mach_error_t AMDeviceLookupApplications(am_device device, CFDictionaryRef options, CFDictionaryRef *result);
 
 // 0000251f T _AMDeviceActivate (am_device, int32 )
 // 000088ad T _AMDeviceArchiveApplication (am_device, int32, int32, int32, int32)
 @synthesize udid=_udid;
 @synthesize deviceName=_deviceName;
 @synthesize lasterror=_lasterror;
+@synthesize applicationAttributes = _applAttributes;
 
 - (void)clearLastError
 {
 	return result;
 }
 
+// At around iOS6.0, we started seeing a new console log message
+//
+//		AMDeviceBrowseApplications was called without specifying an options dictionary
+//		containing kLookupReturnAttributesKey. This usage is inefficient and may cause
+//		performance problems. Break on AMDeviceSlowLookupBreak to debug.
+//
+// Previously, I thought that AMDeviceLookupApplications second argument was a
+// string - it appears that it is a dictionary containing options.
+// The entry keyed by "ReturnAttributes" needs to be an NSArray of strings, each
+// of which is a key into the info dictionary it returns for each app.
+//
+// If you omit the entry for "CFBundleIdentifier", you see console warnings like this:
+//
+//		browse_callback (thread 0xb029a000): Could not extract identifier for entry 1 of 10
+//
+// This method returns an appropriate dictionary
+- (CFDictionaryRef)defaultReturnAttributes
+{
+	NSArray *a = self.applicationAttributes;
+	if (a == nil) {
+		a = [NSArray arrayWithObjects:
+				@"CFBundleIdentifier",			// absolute must
+				@"ApplicationDSID",
+				@"ApplicationType",
+				@"CFBundleExecutable",
+				@"CFBundleDisplayName",
+				@"CFBundleIconFile",
+				@"CFBundleName",
+				@"CFBundleShortVersionString",
+				@"CFBundleSupportedPlatforms",
+				@"CFBundleURLTypes",
+//				@"CodeInfoIdentifier",
+				@"Container",
+//				@"Entitlements",
+//				@"HasSettingsBundle",
+//				@"IsUpgradeable",
+				@"MinimumOSVersion",
+//				@"Path",
+//				@"SignerIdentity",
+				@"UIDeviceFamily",
+				@"UIFileSharingEnabled",
+				@"UIStatusBarHidden",
+				@"UISupportedInterfaceOrientations",
+				nil];
+	}
+
+	NSDictionary *options = [NSDictionary dictionaryWithObject:a forKey:@"ReturnAttributes"];
+	return (CFDictionaryRef)options;
+}
+
 - (NSArray*)installedApplications
 {
 	NSMutableArray* result = nil;
 	if ([self deviceConnect]) {
 		if ([self startSession]) {
 			CFDictionaryRef dict = nil;
+			CFDictionaryRef options = [self defaultReturnAttributes];
 			if (
-				[self checkStatus:AMDeviceLookupApplications(_device, nil, &dict)
+				[self checkStatus:AMDeviceLookupApplications(_device, options, &dict)
 							 from:"AMDeviceLookupApplications"]
 			) {
 				result = [[NSMutableArray new] autorelease];
+				// each key here is the ID of an application
 				for (NSString *key in (NSDictionary*)dict) {
 					NSDictionary *info = [(NSDictionary*)dict objectForKey:key];
 					// "User", "System", "Internal" ??
 	if ([self deviceConnect]) {
 		if ([self startSession]) {
 			CFDictionaryRef dict = nil;
+			CFDictionaryRef options = (CFDictionaryRef)[self defaultReturnAttributes];
 			if (
-				[self checkStatus:AMDeviceLookupApplications(_device, nil, &dict)
+				[self checkStatus:AMDeviceLookupApplications(_device, options, &dict)
 							 from:"AMDeviceLookupApplications"]
 			) {
 				NSDictionary *info = [(NSDictionary*)dict objectForKey:id];
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.