Commits

Jeff Laing committed 9656f10

More stuff to do with the installation proxy

  • Participants
  • Parent commits 94cb69b

Comments (0)

Files changed (2)

File MobileDeviceAccess.h

 
 /// Ask the installation daemon on the device to install an application.  pathname
 /// must be the name of a directory located in /var/mobile/Media and must contain
-/// a pre-expanded .app
+/// a pre-expanded .app which must not already exist on the device
 - (BOOL)install:(NSString*)pathname;
 
+/// Ask the installation daemon on the device to upgrade an application.  pathname
+/// must be the name of a directory located in /var/mobile/Media and must contain
+/// a pre-expanded .app which already exists on the device
+- (BOOL)upgrade:(NSString*)bundleId from:(NSString*)pathname;
+
 @end
 
 /// This class communicates with the MobileSync service.  There is a fairly complicated protocol
 /// by iTunes.  For other (system) applications, use NSInstallationProxy to browse.
 - (NSArray*)installedApplications;
 
+/// Check whether the specified bundleId corresponds to an application
+/// installed on the device.  If so, return an appropriate AMApplication.
+/// Otherwise return nil.
+- (AMApplication*)installedApplicationWithId:(NSString*)bundleId;
+
 @end
 
 /// An object must implement this protocol if it is to be passed as a listener

File MobileDeviceAccess.m

 	return NO;
 }
 
+- (BOOL)upgrade:(NSString*)bundleId from:(NSString*)pathname;
+{
+	NSDictionary *message;
+	message = [NSDictionary dictionaryWithObjectsAndKeys:
+					// value					key
+					@"Upgrade",				@"Command",
+					pathname,				@"PackagePath",
+					bundleId,				@"ApplicationIdentifier",
+					[NSDictionary dictionaryWithObjectsAndKeys:
+						@"Developer", @"PackageType",
+						nil],				@"ClientOptions",
+					nil];
+	[self performDelegateSelector:@selector(operationStarted:) withObject:message];
+	if ([self sendXMLRequest:message]) {
+		for (;;) {
+			// read next slab of information
+			// The reply will contain an entry for Status, a string from the following:
+			//	"RemovingArchive"
+			//	"Complete"
+			// All except "Complete" also include PercentageComplete, an integer between 0 and 100 (but it goes up and down)
+			//
+			// Looks like instead of Status, we can get:
+			// Error = APIEpicFail;
+			// (that happened if I passed in a missing bundle-id
+			// Error = APIInternalError
+			// (that happened if I kept reading?
+			NSDictionary *reply = [self readXMLReply];
+			if (!reply) break;
+			[self performDelegateSelector:@selector(operationContinues:) withObject:reply];
+			NSString *s = [reply objectForKey:@"Status"];
+			if ([s isEqual:@"Complete"]) break;
+		}
+	}
+	[self performDelegateSelector:@selector(operationCompleted:) withObject:message];
+	return NO;
+}
+
 @end
 
 @implementation AMSyslogRelay
 	return result;
 }
 
+- (AMApplication*)installedApplicationWithId:(NSString*)id
+{
+	AMApplication* result = nil;
+	if ([self deviceConnect]) {
+		if ([self startSession]) {
+			CFDictionaryRef dict = nil;
+			if (
+				[self checkStatus:AMDeviceLookupApplications(_device, nil, &dict)
+							 from:"AMDeviceLookupApplications"]
+			) {
+				NSDictionary *info = [(NSDictionary*)dict objectForKey:id];
+				if (info) {
+					result = [[[AMApplication alloc] initWithDictionary:info] autorelease];
+				}
+				CFRelease(dict);
+			}
+			[self stopSession];
+		}
+		[self deviceDisconnect];
+	}
+	return result;
+}
+
 @end
 
 @implementation MobileDeviceAccess