Compare commits
	
		
			17 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 125cd8de64 | ||
|   | 7070623432 | ||
|   | d712420e60 | ||
|   | 2c35b70ff7 | ||
|   | ea8202c506 | ||
|   | 7c1372041d | ||
|   | b67b90be19 | ||
|   | 9156689720 | ||
|   | a89b71bdf4 | ||
|   | 6e4df1cc07 | ||
|   | fc667bc423 | ||
|   | 2119c10455 | ||
|   | 1db084594e | ||
|   | 8d1f79d27c | ||
|   | 8c9dab1564 | ||
|   | 54a04e203f | ||
|   | c1a0623e49 | 
							
								
								
									
										6
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Makefile
									
									
									
									
									
								
							| @@ -1,10 +1,10 @@ | ||||
| IOS_SDK_VERSION = 7.1 | ||||
| IOS_SDK_VERSION = 8.3 | ||||
|  | ||||
| IOS_CC = gcc -ObjC | ||||
| DEVICE_SUPPORT = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/DeviceSupport | ||||
| IOS_SDK = $(shell xcode-select --print-path)/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS$(IOS_SDK_VERSION).sdk | ||||
|  | ||||
| all: clean ios-deploy | ||||
| all: clean ios-deploy demo.app | ||||
|  | ||||
| demo.app: demo Info.plist | ||||
| 	mkdir -p demo.app | ||||
| @@ -32,4 +32,4 @@ debug: all | ||||
| 	./ios-deploy --debug --bundle demo.app | ||||
|  | ||||
| clean: | ||||
| 	rm -rf *.app demo ios-deploy | ||||
| 	@rm -rf *.app demo ios-deploy | ||||
|   | ||||
							
								
								
									
										55
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										55
									
								
								README.md
									
									
									
									
									
								
							| @@ -4,20 +4,31 @@ Install and debug iOS apps without using Xcode. Designed to work on un-jailbroke | ||||
|  | ||||
| ## Requirements | ||||
|  | ||||
| * Mac OS X. Tested on 10.10 Yosemite and iOS 8.1 | ||||
| * You need to have a valid iOS development certificate installed. | ||||
| * Xcode 6.1 should be installed | ||||
| * Mac OS X. Tested on 10.10 Yosemite and iOS 8.3 | ||||
| * You need to have a valid iOS Development certificate installed. | ||||
| * Xcode 6 or greater should be installed | ||||
|  | ||||
| ## Installation | ||||
| ios-deploy installation is made simple using the node.js package manager.  If you use [Homebrew](http://brew.sh/), install node.js: | ||||
| ```bash | ||||
|  | ||||
| ios-deploy installation is made simple using the node.js package manager.  If you use [Homebrew](http://brew.sh/), install [node.js](https://nodejs.org): | ||||
|  | ||||
| ``` | ||||
| brew install node | ||||
| ``` | ||||
|  | ||||
| Now install ios-deploy with the node.js package manager: | ||||
| ```bash | ||||
| $ npm install -g ios-deploy | ||||
| Now install ios-deploy with the [node.js](https://nodejs.org) package manager: | ||||
|  | ||||
| ``` | ||||
| npm install -g ios-deploy | ||||
| ``` | ||||
|  | ||||
| To install from source: | ||||
|  | ||||
| ``` | ||||
| make install prefix=/usr/local | ||||
| ``` | ||||
|  | ||||
| This will install ios-deploy in the `bin` folder of `/usr/local`, i.e. `/usr/local/bin` | ||||
|  | ||||
| ## Usage | ||||
|  | ||||
| @@ -36,11 +47,14 @@ $ npm install -g ios-deploy | ||||
|       -m, --noinstall              directly start debugging without app install (-d not required) | ||||
|       -p, --port <number>          port used for device, default: 12345 | ||||
|       -r, --uninstall              uninstall the app before install (do not use with -m; app cache and data are cleared) | ||||
|       -1, --bundle_id <bundle id>  specify bundle id for list and upload | ||||
|       -9, --uninstall_only         uninstall the app ONLY. Use only with -1 <bundle_id>  | ||||
|       -1, --bundle_id <bundle id>  specify bundle id for list, upload, and uninstall_only | ||||
|       -l, --list                   list files | ||||
|       -o, --upload <file>          upload file | ||||
|       -w, --download               download app tree | ||||
|       -2, --to <target pathname>   use together with up/download file/tree. specify target | ||||
|       -D, --mkdir <dir>            make directory on device | ||||
|       -R, --rm <path>              remove file or directory on device (directories must be empty) | ||||
|       -V, --version                print the executable version | ||||
|       -e, --exists                 check if the app with given bundle_id is installed or not | ||||
|  | ||||
| @@ -73,19 +87,22 @@ The commands below assume that you have an app called `my.app` with bundle id `b | ||||
|     // check whether an app by bundle id exists on the device (check return code `echo $?`) | ||||
|     ios-deploy --exists --bundle_id com.apple.mobilemail | ||||
|  | ||||
|     // Download the Documents directory of the app *only* | ||||
|     ios-deploy --download=/Documents -bundle_id my.app.id --to ./my_download_location | ||||
|      | ||||
|     // List ids and names of connected devices | ||||
|     ios-deploy -c | ||||
|      | ||||
|     // Uninstall an app | ||||
|     ios-deploy --uninstall_only --bundle_id my.bundle.id | ||||
|  | ||||
| ## Demo | ||||
|  | ||||
| * The included demo.app represents the minimum required to get code running on iOS. | ||||
| * `make install` will install demo.app to the device. | ||||
| * `make debug` will install demo.app and launch a GDB session. | ||||
| The included demo.app represents the minimum required to get code running on iOS. | ||||
|  | ||||
| * `make demo.app` will generate the demo.app executable. If it doesn't compile, modify IOS_SDK_VERSION in the Makefile. | ||||
| * `make debug` will install demo.app and launch a LLDB session. | ||||
|  | ||||
| ## Notes | ||||
|  | ||||
| * With some modifications, it may be possible to use this without Xcode installed; however, you would need a copy of the relevant DeveloperDiskImage.dmg (included with Xcode). lldb would also run slower as symbols would be downloaded from the device on-the-fly. | ||||
|  | ||||
|  | ||||
| ## Listing Device Ids | ||||
|  | ||||
| Device Ids are the UDIDs of the iOS devices. From the command line, you can list device ids [this way](http://javierhz.blogspot.com/2012/06/how-to-get-udid-of-iphone-using-shell.html): | ||||
|  | ||||
|         system_profiler SPUSBDataType | sed -n -e '/iPod/,/Serial/p' | sed -n -e '/iPad/,/Serial/p' -e '/iPhone/,/Serial/p' | grep "Serial Number:" | awk -F ": " '{print $2}' | ||||
|   | ||||
							
								
								
									
										112
									
								
								ios-deploy.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								ios-deploy.c
									
									
									
									
									
								
							| @@ -16,7 +16,7 @@ | ||||
| #include <netinet/tcp.h> | ||||
| #include "MobileDevice.h" | ||||
|  | ||||
| #define APP_VERSION    "1.5.0" | ||||
| #define APP_VERSION    "1.6.1" | ||||
| #define PREP_CMDS_PATH "/tmp/fruitstrap-lldb-prep-cmds-" | ||||
| #define LLDB_SHELL "lldb -s " PREP_CMDS_PATH | ||||
| /* | ||||
| @@ -1454,6 +1454,67 @@ void upload_file(AMDeviceRef device) { | ||||
|     free(file_content); | ||||
| } | ||||
|  | ||||
| void make_directory(AMDeviceRef device) { | ||||
|     service_conn_t houseFd = start_house_arrest_service(device); | ||||
|  | ||||
|     afc_file_ref file_ref; | ||||
|  | ||||
|     afc_connection afc_conn; | ||||
|     afc_connection* afc_conn_p = &afc_conn; | ||||
|     AFCConnectionOpen(houseFd, 0, &afc_conn_p); | ||||
|  | ||||
|     assert(AFCDirectoryCreate(afc_conn_p, target_filename) == 0); | ||||
|     assert(AFCConnectionClose(afc_conn_p) == 0); | ||||
| } | ||||
|  | ||||
| void remove_path(AMDeviceRef device) { | ||||
|     service_conn_t houseFd = start_house_arrest_service(device); | ||||
|  | ||||
|     afc_file_ref file_ref; | ||||
|  | ||||
|     afc_connection afc_conn; | ||||
|     afc_connection* afc_conn_p = &afc_conn; | ||||
|     AFCConnectionOpen(houseFd, 0, &afc_conn_p); | ||||
|  | ||||
|  | ||||
|     assert(AFCRemovePath(afc_conn_p, target_filename) == 0); | ||||
|     assert(AFCConnectionClose(afc_conn_p) == 0); | ||||
| } | ||||
|  | ||||
| void uninstall_app(AMDeviceRef device) { | ||||
|     CFRetain(device); // don't know if this is necessary? | ||||
|  | ||||
|     printf("------ Uninstall phase ------\n"); | ||||
|  | ||||
|     //Do we already have the bundle_id passed in via the command line? if so, use it. | ||||
|     CFStringRef cf_uninstall_bundle_id = NULL; | ||||
|     if (bundle_id != NULL) | ||||
|     { | ||||
|         cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); | ||||
|     } else { | ||||
|         printf ("Error: you need to pass in the bundle id, (i.e. --bundle_id com.my.app)"); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     if (cf_uninstall_bundle_id == NULL) { | ||||
|         printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); | ||||
|     } else { | ||||
|         AMDeviceConnect(device); | ||||
|         assert(AMDeviceIsPaired(device)); | ||||
|         assert(AMDeviceValidatePairing(device) == 0); | ||||
|         assert(AMDeviceStartSession(device) == 0); | ||||
|  | ||||
|         int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); | ||||
|         if (code == 0) { | ||||
|             printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); | ||||
|         } else { | ||||
|             printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); | ||||
|         } | ||||
|         assert(AMDeviceStopSession(device) == 0); | ||||
|         assert(AMDeviceDisconnect(device) == 0); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void handle_device(AMDeviceRef device) { | ||||
|     //if (found_device) | ||||
|     //    return; // handle one device only | ||||
| @@ -1488,8 +1549,14 @@ void handle_device(AMDeviceRef device) { | ||||
|             upload_file(device); | ||||
|         } else if (strcmp("download", command) == 0) { | ||||
|             download_tree(device); | ||||
|         } else if (strcmp("mkdir", command) == 0) { | ||||
|             make_directory(device); | ||||
|         } else if (strcmp("rm", command) == 0) { | ||||
|             remove_path(device); | ||||
|         } else if (strcmp("exists", command) == 0) { | ||||
|             exit(app_exists(device)); | ||||
|         } else if (strcmp("uninstall_only", command) == 0) { | ||||
|             uninstall_app(device); | ||||
|         } | ||||
|         exit(0); | ||||
|     } | ||||
| @@ -1506,20 +1573,28 @@ void handle_device(AMDeviceRef device) { | ||||
|     if (uninstall) { | ||||
|         printf("------ Uninstall phase ------\n"); | ||||
|  | ||||
|         CFStringRef bundle_id = get_bundle_id(url); | ||||
|         if (bundle_id == NULL) { | ||||
|             printf("Error: Unable to get bundle id from package %s\n Uninstall failed\n", app_path); | ||||
|         //Do we already have the bundle_id passed in via the command line? if so, use it. | ||||
|         CFStringRef cf_uninstall_bundle_id = NULL; | ||||
|         if (bundle_id != NULL) | ||||
|         { | ||||
|             cf_uninstall_bundle_id = CFStringCreateWithCString(NULL, bundle_id, kCFStringEncodingASCII); | ||||
|         } else { | ||||
|             cf_uninstall_bundle_id = get_bundle_id(url); | ||||
|         } | ||||
|  | ||||
|         if (cf_uninstall_bundle_id == NULL) { | ||||
|             printf("Error: Unable to get bundle id from user command or package %s\n Uninstall failed\n", app_path); | ||||
|         } else { | ||||
|             AMDeviceConnect(device); | ||||
|             assert(AMDeviceIsPaired(device)); | ||||
|             assert(AMDeviceValidatePairing(device) == 0); | ||||
|             assert(AMDeviceStartSession(device) == 0); | ||||
|  | ||||
|             int code = AMDeviceSecureUninstallApplication(0, device, bundle_id, 0, NULL, 0); | ||||
|             int code = AMDeviceSecureUninstallApplication(0, device, cf_uninstall_bundle_id, 0, NULL, 0); | ||||
|             if (code == 0) { | ||||
|                 printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); | ||||
|                 printf("[ OK ] Uninstalled package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); | ||||
|             } else { | ||||
|                 printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(bundle_id, CFStringGetSystemEncoding())); | ||||
|                 printf("[ ERROR ] Could not uninstall package with bundle id %s\n", CFStringGetCStringPtr(cf_uninstall_bundle_id, CFStringGetSystemEncoding())); | ||||
|             } | ||||
|             assert(AMDeviceStopSession(device) == 0); | ||||
|             assert(AMDeviceDisconnect(device) == 0); | ||||
| @@ -1665,11 +1740,14 @@ void usage(const char* app) { | ||||
|         "  -m, --noinstall              directly start debugging without app install (-d not required)\n" | ||||
|         "  -p, --port <number>          port used for device, default: dynamic\n" | ||||
|         "  -r, --uninstall              uninstall the app before install (do not use with -m; app cache and data are cleared) \n" | ||||
|         "  -9, --uninstall_only         uninstall the app ONLY. Use only with -1 <bundle_id> \n" | ||||
|         "  -1, --bundle_id <bundle id>  specify bundle id for list and upload\n" | ||||
|         "  -l, --list                   list files\n" | ||||
|         "  -o, --upload <file>          upload file\n" | ||||
|         "  -w, --download               download app tree\n" | ||||
|         "  -2, --to <target pathname>   use together with up/download file/tree. specify target\n" | ||||
|         "  -D, --mkdir <dir>            make directory on device\n" | ||||
|         "  -R, --rm <path>              remove file or directory on device (directories must be empty)\n" | ||||
|         "  -V, --version                print the executable version \n" | ||||
|         "  -e, --exists                 check if the app with given bundle_id is installed or not \n", | ||||
|         app); | ||||
| @@ -1696,17 +1774,20 @@ int main(int argc, char *argv[]) { | ||||
|         { "noinstall", no_argument, NULL, 'm' }, | ||||
|         { "port", required_argument, NULL, 'p' }, | ||||
|         { "uninstall", no_argument, NULL, 'r' }, | ||||
|         { "uninstall_only", no_argument, NULL, '9'}, | ||||
|         { "list", optional_argument, NULL, 'l' }, | ||||
|         { "bundle_id", required_argument, NULL, '1'}, | ||||
|         { "upload", required_argument, NULL, 'o'}, | ||||
|         { "download", optional_argument, NULL, 'w'}, | ||||
|         { "to", required_argument, NULL, '2'}, | ||||
|         { "mkdir", required_argument, NULL, 'D'}, | ||||
|         { "rm", required_argument, NULL, 'R'}, | ||||
|         { "exists", no_argument, NULL, 'e'}, | ||||
|         { NULL, 0, NULL, 0 }, | ||||
|     }; | ||||
|     char ch; | ||||
|  | ||||
|     while ((ch = getopt_long(argc, argv, "VmcdvunrILei:b:a:t:g:x:p:1:2:o:l::w::", longopts, NULL)) != -1) | ||||
|     while ((ch = getopt_long(argc, argv, "VmcdvunrILeD:R:i:b:a:t:g:x:p:1:2:o:l::w::9::", longopts, NULL)) != -1) | ||||
|     { | ||||
|         switch (ch) { | ||||
|         case 'm': | ||||
| @@ -1757,6 +1838,10 @@ int main(int argc, char *argv[]) { | ||||
|         case 'r': | ||||
|             uninstall = 1; | ||||
|             break; | ||||
|         case '9': | ||||
|             command_only = true; | ||||
|             command = "uninstall_only"; | ||||
|             break; | ||||
|         case '1': | ||||
|             bundle_id = optarg; | ||||
|             break; | ||||
| @@ -1778,6 +1863,16 @@ int main(int argc, char *argv[]) { | ||||
|             command = "download"; | ||||
|             list_root = optarg; | ||||
|             break; | ||||
|         case 'D': | ||||
|             command_only = true; | ||||
|             target_filename = optarg; | ||||
|             command = "mkdir"; | ||||
|             break; | ||||
|         case 'R': | ||||
|             command_only = true; | ||||
|             target_filename = optarg; | ||||
|             command = "rm"; | ||||
|             break; | ||||
|         case 'e': | ||||
|             command_only = true; | ||||
|             command = "exists"; | ||||
| @@ -1790,6 +1885,7 @@ int main(int argc, char *argv[]) { | ||||
|  | ||||
|     if (!app_path && !detect_only && !command_only) { | ||||
|         usage(argv[0]); | ||||
|         printf ("ERROR: One of -[b|c|o|l|w|D|R|e|9] is required to proceed!\n"); | ||||
|         exit(exitcode_error); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| { | ||||
|   "name": "ios-deploy", | ||||
|   "version": "1.5.0", | ||||
|   "version": "1.6.1", | ||||
|   "os" : [ "darwin" ], | ||||
|   "description": "launch iOS apps iOS devices from the command line (Xcode 6)", | ||||
|   "main": "ios-deploy", | ||||
|   "scripts": { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user