반응형

문득 iOS 앱을 터미널에서 실행시킬 수 있는 방법은 없을까하는 생각이 들었습니다.

이미 "Open for iOS 11" 이라는 Command line 툴이 있지만, Theos tool 제작 연습해볼겸 구글링하여 만들어보았습니다.

iOS 13.5.1, iOS 14.2 에서 테스트결과 정상 작동합니다. 단, "applist" 트윅에 의존적이라 해당 트윅이 설치되어 있어야 합니다.

com.hackcatml.listapp_0.0.1_iphoneos-arm.deb
0.00MB

 

사용법은 다음과 같습니다.

"listapp" 또는 "listapp -l" 명령어를 입력하면 현재 설치된 앱의 BundleID와 DisplayName을 확인할 수 있습니다.

 

 

"listapp -o <BundleID>" 명령어를 입력하면 앱이 실행됩니다.

 

 

조악하지만 소스코드는 다음과 같습니다.

- main.m

// AppList library는 /var/theos/vendor/include/, /var/theos/vendor/lib/ 에 위치
#import <AppList/AppList.h>
#include <dlfcn.h>
#include <stdio.h>

void showHelp(){
	printf("\nUsage: listapp [options]\n\n");
	printf("Options:\n");
	printf("\t-l: List Installed AppStore Apps\n");
	printf("\t-o <BundleId>: Open an App (ex. listapp -o com.hackcatml.example)\n");
	printf("\t-h: show help\n\n");
}

NSDictionary *applicationList(){
	// library open
	void *handler = dlopen("/usr/lib/libapplist.dylib", RTLD_NOW);
	if (handler == NULL) {
    	printf("Got dlopen error!\n\n");
		return nil;
  	} 
	else {
		// sort the apps by display name. displayIdentifiers is an autoreleased object.
		NSArray *sortedDisplayIdentifiers;
		NSDictionary *applications = [[NSClassFromString(@"ALApplicationList") sharedApplicationList] 
			applicationsFilteredUsingPredicate:[NSPredicate predicateWithFormat:@"isSystemApplication = FALSE"]
			onlyVisible:YES titleSortedIdentifiers:&sortedDisplayIdentifiers];
		dlclose(handler);
		return applications;
	}
}

void listApp(){
	NSDictionary *applications = applicationList();
	printf("\nBundleID - DisplayName");
	printf("\n-------------------------------------------\n");
	for(NSString *key in applications){
		printf("\"%s\" - \"%s\"\n", [key UTF8String], [applications[key] UTF8String]);
	}
	printf("-------------------------------------------\n");
}

void openApp(NSString *BundleId){
	// library open. 해당 라이브러를 열어야 LSApplicationWorkspace 클래스 사용 가능.
	void *handler = dlopen("/System/Library/Frameworks/MobileCoreServices.framework/MobileCoreServices", RTLD_NOW);

	if (handler == NULL) {
    	printf("Got dlopen error!\n\n");
  	} 
	else {
		id Hackcatml = [NSClassFromString(@"LSApplicationWorkspace") performSelector:@selector(defaultWorkspace)];
		[Hackcatml performSelector:@selector(openApplicationWithBundleID:) withObject:BundleId];
		printf("Open \"%s\"\n\n", [BundleId UTF8String]);
	}
}

int main(int argc, char *argv[], char *envp[]) {
	@autoreleasepool {
		// Process parameters
		NSArray *arguments =[[NSProcessInfo processInfo] arguments];

		if([arguments count] == 1){
			listApp();
			return 0;
		}
		else if([arguments count] >= 2 && [arguments count] <= 3){
			NSString *op1 = [arguments objectAtIndex:1];
			if([op1 isEqualToString:@"-l"]){
				listApp();
				return 0;
			} else if([op1 isEqualToString:@"-o"]){
				if([arguments count] == 2){
					printf("\nYou should specify BundleId");
					printf("\nEx) listapp -o com.hackcatml.test\n\n");
					return -1;
				} else {
					NSString *op2 = [arguments objectAtIndex:2];
					openApp(op2);
					return 0;
				}
			} else if([op1 isEqualToString:@"-h"] || [op1 isEqualToString:@"--help"]){
				showHelp();
				return 0;
			} else {
				printf("\nUsage: listApp [options]. see --help\n\n");	
			}
		}
		else {
			printf("\nUsage: listApp [options]. see --help\n\n");
		}
	}
	return 0;
}

 

 

※ 출처

https://github.com/insidegui/launchapp/blob/master/launchapp/main.m(launchapp. iOS 13에서 작동하지 않음)

https://developer.limneos.net/index.php?ios=11.0&framework=MobileCoreServices.framework&header=LSApplicationWorkspace.h(LSApplicationWorkspace header)

https://answer-id.com/ru/54280161

https://www.reddit.com/r/jailbreak/comments/db1i87/question_how_to_open_apps_from_terminal/ (Open for iOS 11 tweak)

https://github.com/autopear/ipainstaller/blob/master/main.mm (ipainstaller old github)

https://iphonedev.wiki/index.php/AppList (AppList 라이브러리 사용법 iPhoneDevWiki)

 

반응형

+ Recent posts